Swift 2.2弃用了C风格的循环。但是在某些情况下,新范围运算符的工作方式不同。
for var i = 0; i < -1; ++i { ... }
和
for i in 0..<-1 { ... }
后者将在运行时失败。我可以使用if
包裹循环,但它有点混乱。有时这种循环很有用。
有什么想法吗?
使用案例
答案 0 :(得分:20)
虽然它不是“漂亮”,但您可以使用stride
:
for var i in 0.stride(to: -1, by: -1) {
print(i)
}
答案 1 :(得分:9)
不完全漂亮,但你可以用max(0, ..)
包裹范围:s上限,以确定它永远不会带负值。
let foo : [Int] = []
for i in 0..<max(0,foo.count-1) {
print(i)
}
然而,我更喜欢from.stride(to:by)
解决方案(其他答案中已经提到过,例如迈克尔的回答)。
我认为明确指出from.stride(to:by)
如果试图跨步,整齐地返回一个空的StrideTo
(或者,如果转换为数组:一个空数组),我认为很有价值。 一个小于的数字但 一个正步幅。例如,0
从-42
跨越1
将不会尝试一直跨越"∞ -> -∞ -> -42"
(即错误情况),但只返回一个空StrideTo
1}}(应该如此):
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)
}
对于此特定用例,一个简单的解决方案是使用dropLast()
(如Sulthan在您的问题的评论中所述),然后是forEach
。
let foo = Array(1...5)
foo.dropLast().forEach { print($0) } // 1 2 3 4
或者,如果您需要更多地控制要删除的内容,请将过滤器应用于数组
let foo = Array(1...5)
foo.filter { $0 < foo.count }.forEach { print($0) } // 1 2 3 4
对于您的十进制/双闭区间示例([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 */
答案 2 :(得分:4)
供参考: 在swift 3.0中,现在全局定义了stride,这使得循环看起来更自然:
for i in stride(from: 10, to: 0, by: -1){
print(i)
} /* 10 9 8 7 6 5 4 3 2 1 */
答案 3 :(得分:0)
对于Swift 3,需要更改&#34;索引&#34;
for var index in stride(from: 0, to: 10, by: 1){}