Swift 样式循环的多个增量
Multiple increments in Swift style for loops
我的 Swift 代码中有以下循环:
for var i:Int = 0, j:Int = 0; i < rawDataOut.count; i += 4, ++j {
maskPixels[j] = rawDataOut[i + 3]
}
我在 Xcode 中收到两个警告:
- C 风格的 for 语句已弃用,将在 Swift
的未来版本中删除
- '++' 已弃用:它将在 Swift 3
中删除
我看不出如何在 Swift 的 For In Loops 中重写它以考虑到两个变量和 4 步而不会变得混乱。有没有简单优雅的翻译?
回答这个问题的先决条件:查看你的例子
我假设您打算将 i
限制为 i < rawDataOut.count-3
而不是 i < rawDataOut.count
,否则按索引访问 rawDataOut[i + 3]
元素没有多大意义 w.r.t。运行时安全。无论如何,如果您不向我们展示 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
和 enumerate
.
的 2 次迭代方法
合并 stride
和 enumerate
一种解决方案是在上面的循环中枚举迭代i
描述的stride
,并使用枚举索引构造第二个迭代(上面的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
(as non-blueprinted extension methods) will be depracated, and that we're back to (as in Swift 1.2) using the global functions stride(from:to:by:)
and stride(from:through:by:)
, see e.g. the current master branch of swift/stdlib/public/core/Stride.swift
更棘手的情况:诉诸 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 in
、stride
等覆盖,并且对于这些还不够的情况,一个很好的老人' while
,很可能会。
在Swift 4
for index in stride(from: 0, to: 10, by: 2){
print(index)
}
我的 Swift 代码中有以下循环:
for var i:Int = 0, j:Int = 0; i < rawDataOut.count; i += 4, ++j {
maskPixels[j] = rawDataOut[i + 3]
}
我在 Xcode 中收到两个警告:
- C 风格的 for 语句已弃用,将在 Swift 的未来版本中删除
- '++' 已弃用:它将在 Swift 3 中删除
我看不出如何在 Swift 的 For In Loops 中重写它以考虑到两个变量和 4 步而不会变得混乱。有没有简单优雅的翻译?
回答这个问题的先决条件:查看你的例子
我假设您打算将 i
限制为 i < rawDataOut.count-3
而不是 i < rawDataOut.count
,否则按索引访问 rawDataOut[i + 3]
元素没有多大意义 w.r.t。运行时安全。无论如何,如果您不向我们展示 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
和 enumerate
.
合并 stride
和 enumerate
一种解决方案是在上面的循环中枚举迭代i
描述的stride
,并使用枚举索引构造第二个迭代(上面的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
(as non-blueprinted extension methods) will be depracated, and that we're back to (as in Swift 1.2) using the global functions stride(from:to:by:)
and stride(from:through:by:)
, see e.g. the current master branch of swift/stdlib/public/core/Stride.swift
更棘手的情况:诉诸 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 in
、stride
等覆盖,并且对于这些还不够的情况,一个很好的老人' while
,很可能会。
在Swift 4
for index in stride(from: 0, to: 10, by: 2){
print(index)
}