6

我的 Swift 代码中有以下循环:

for var i:Int = 0, j:Int = 0; i < rawDataOut.count; i += 4, ++j {
    maskPixels[j] = rawDataOut[i + 3]
}

我在 Xcode 中收到两个警告:

  1. C 风格的 for 语句已被弃用,并将在 Swift 的未来版本中删除
  2. '++' 已弃用:它将在 Swift 3 中删除

我看不出如何在 Swift 的For In 循环中重写它,以考虑到这两个变量和 4 步长而不会使它变得混乱。有简单优雅的翻译吗?

4

2 回答 2

17

回答这个问题的先决条件:查看您的示例

我将假设您打算限制ibyi < rawDataOut.count-3而不是i < rawDataOut.count,否则rawDataOut[i + 3]通过索引访问元素对运行时安全性没有多大意义。无论如何,如果没有您向我们展示rawDataOut,这是我们必须做出的假设。

因此,您的原始循环(包括可验证的示例)如下所示

/* example data */
var rawDataOut = Array(1...40)
var maskPixels = [Int](count: 10, repeatedValue: 0)

/* your pre-Swift 2.2/3.0 loop */
for var i: Int = 0, j: Int = 0; i < rawDataOut.count-3; i += 4, ++j {
    maskPixels[j] = rawDataOut[i + 3]
}

print(maskPixels) //[4, 8, 12, 16, 20, 24, 28, 32, 36, 40]

使用for in ... where

在您的特定示例中,多个增量具有简单的关系 ( j=4*i),因此我们甚至可以在不使用显式j迭代的情况下解决此问题,例如

/* example data */
var rawDataOut = Array(1...40)
var maskPixels = [Int](count: 10, repeatedValue: 0)

/* your pre-Swift 2.2/3.0 loop */
for i in 0..<(rawDataOut.count-3) where i%4 == 0 {
    maskPixels[i/4] = rawDataOut[i + 3]
}

print(maskPixels) // [4, 8, 12, 16, 20, 24, 28, 32, 36, 40]

但这对于两个迭代的一般讨论可能并不真正感兴趣。我们继续使用结合stride和的 2 次迭代方法enumerate


结合strideenumerate

一种解决方案是在上面的循环中枚举stride由迭代描述的内容i,并使用枚举索引来构造第二个迭代(j上面)。在您的示例中,enumerate索引完全对应于j,即

/* example data */
var rawDataOut = Array(1...40)
var maskPixels = [Int](count: 10, repeatedValue: 0)

/* Swift >= 2.2 loop */
for (j, i) in 0.stride(to: rawDataOut.count-3, by: 4).enumerate() {
    maskPixels[j] = rawDataOut[i + 3]
}

print(maskPixels) // [4, 8, 12, 16, 20, 24, 28, 32, 36, 40]

请注意,在 Swift 3(与 2.2 相比)中,似乎stride(to:by:)stride(through:by:)协议的默认实现Strideable(作为非蓝图扩展方法)将被弃用,并且我们回到(如在 Swift 1.2 中)使用全局函数stride(from:to:by:)和,参见例如swift/stdlib/public/core/Stride.swiftstride(from:through:by:)的当前主分支


更棘手的案例:诉诸while

对于更棘手的情况,请在 Swift 2.2 之前的循环中说一个签名为

for var i: Int = 0, j: Int = 0; i < rawDataOut.count-3; i += 4, j += i { ... }

你可能最好简单地使用一个while循环,其中一个迭代与循环不变量相关联,一个尾随迭代作为自由变量;我想这是否被认为是混乱的,是一个品味问题。

var i = 0, j = 0
while i < rawDataOut.count-3 {

    // ...

    // increase iterates
    i += 4
    j += i
}

我认为删除 C 样式循环的原因是,在大多数情况下,它直接由 等覆盖for instride而对于这些还不够的情况,while很可能会使用旧的' 。

于 2016-03-29T21:59:51.470 回答
7

在斯威夫特 4

for index in stride(from: 0, to: 10, by: 2){
    print(index)
}
于 2017-10-27T05:44:34.793 回答