replaceSwift 2.2中的C风格的循环
Swift 2.2弃用了C风格的循环。 但是,在某些情况下,新的范围运算符只是工作不一样。
for var i = 0; i < -1; ++i { ... }
和
for i in 0..<-1 { ... }
后者在运行时会失败。 我可以用if
包裹循环,但是有点混乱。 有时这种循环是有用的。
有什么想法吗?
用例
- 您需要枚举数组中的所有元素,除了最后一个。
- 你需要枚举所有整数在十进制范围内,但范围可以像[0.5,0.9],所以没有整数(在一些math后),这将导致一个空循环。
虽然不是“漂亮”,但可以使用stride
:
for var i in 0.stride(to: -1, by: -1) { print(i) }
模仿“C式循环”
不完全漂亮,但你可以用范围上限max(0, ..)
来确定它从不取负值。
let foo : [Int] = [] for i in 0..<max(0,foo.count-1) { print(i) }
但是,我更喜欢from.stride(to:by)
解决scheme(在其他答案中已经提到过,例如参见Michael的答案)。
然而,我认为明确地指出from.stride(to:by)
整齐地返回一个空的StrideTo
(或者,如果转换为数组:一个空数组),如果试图跨越一个小于而是通过积极的步伐。 例如,从0
到-42
,不会试图通过"∞ -> -∞ -> -42"
(即错误情况) StrideTo
,而是简单地返回一个空的StrideTo
(它应该):
Array(0.stride(to: -42, by: 1)) // [] // -> equivalent to your C loop: for i in 0.stride(to: foo.count-1, by: 1) { print(i) }
使用案例1:枚举除数组的最后一个元素外的所有元素
对于这个特定的用例,一个简单的解决scheme是使用dropLast()
(在Sulthan中对你的问题的评论中描述),然后是forEach
。
let foo = Array(1...5) foo.dropLast().forEach { print($0) } // 1 2 3 4
或者,如果您需要更多控制要删除的内容,请将filter应用于您的arrays
let foo = Array(1...5) foo.filter { $0 < foo.count }.forEach { print($0) } // 1 2 3 4
用例2:枚举小数范围内的所有整数,允许此枚举为空
对于你的十进制/双闭区间示例( [0.6, 0.9]
;一个区间而不是Swift语法中的区间),可以将闭区间转换为一个整数范围(使用ceil
函数),并将forEach
后者
let foo : (ClosedInterval<Double>) -> () = { (Int(ceil($0.start))..<Int(ceil($0.end))) .forEach { print($0) } } foo(0.5...1.9) // 1 foo(0.5...0.9) // nothing
或者,如果您特意要枚举此区间中包含的(可能的)整数, 用作符合您的目的的扩展名:
protocol MyDoubleBounds { func ceilToInt() -> Int } extension Double: MyDoubleBounds { func ceilToInt() -> Int { return Int(ceil(self)) // no integer bounds check in this simple example } } extension ClosedInterval where Bound: MyDoubleBounds { func enumerateIntegers() -> EnumerateSequence<(Range<Int>)> { return (self.start.ceilToInt() ..< self.end.ceilToInt()) .enumerate() } }
用法示例:
for (i, intVal) in (1.3...3.2).enumerateIntegers() { print(i, intVal) } /* 0 2 1 3 */ for (i, intVal) in (0.6...0.9).enumerateIntegers() { print(i, intVal) } /* nothing */
作为参考:在swift 3.0中,现在定义了全局,这使得循环看起来更自然:
for i in stride(from: 10, to: 0, by: -1){ print(i) } /* 10 9 8 7 6 5 4 3 2 1 */
对于Swift 3,需要更改“索引”
for var index in stride(from: 0, to: 10, by: 1){}