Swift中的反向范围
有没有办法在Swift中使用反向范围?
例如:
for i in 5...1 { // do something }
是一个无限循环。
我知道我可以用1..5
代替,计算j = 6 - i
并用j
作为我的索引。 我只是想知道是否有更清晰的文字?
更新最新的Swift 3
你可以使用reverse()方法
for i in (1...5).reversed() { print(i) } // 5 4 3 2 1
或者步幅(from:to:by:)方法
for i in stride(from:5,to:1,by:-1) { print(i) } // 5 4 3 2 1
更新最新的Swift 2
首先,协议扩展改变了如何使用reverse
:
for i in (1...5).reverse() { print(i) } // 5 4 3 2 1
Stride已经在Xcode 7 Beta 6中重新devise了。新的用法是:
for i in 0.stride(to: -8, by: -2) { print(i) } // 0 -2 -4 -6 for i in 0.stride(through: -8, by: -2) { print(i) } // 0 -2 -4 -6 -8
它也适用于Doubles
:
for i in 0.5.stride(to:-0.1, by: -0.1) { print(i) }
小心浮点比较这里的界限。
早期编辑Swift 1.2 :从Xcode 6 Beta 4开始, by和ReverseRange不存在了:[
如果你只是想扭转一个范围, 反向function就是你所需要的:
for i in reverse(1...5) { println(i) } // prints 5,4,3,2,1
由0x7fffffff发布,有一个新的stride结构可以用来迭代和增加任意整数。 苹果还表示,浮点支持即将到来。
从他的答案来源:
for x in stride(from: 0, through: -8, by: -2) { println(x) // 0, -2, -4, -6, -8 } for x in stride(from: 6, to: -2, by: -4) { println(x) // 6, 2 }
有一件令人不安的事情是这样的不对称:
for i in (1..<5).reverse()
…与此相反:
for i in 1..<5 {
这意味着每次我想做一个相反的范围,我都必须记住括号,而且我必须在最后写上.reverse()
,就像拇指一样伸出手。 与C样式的循环相比,这是非常丑陋的,这些循环是对称计数和倒计数。 所以我倾向于使用C风格的循环代替。 但在Swift 2.2中,C风格的循环已经消失了! 所以我不得不花费一些时间,用这个丑陋的.reverse()
构造.reverse()
换掉所有recursion的C风格的循环,为什么地球上不存在反向运算符?
可是等等! 这是Swift – 我们被允许定义我们自己的操作员! 开始了:
infix operator >>> { associativity none precedence 135 } func >>> <Pos : ForwardIndexType where Pos : Comparable>(end:Pos, start:Pos) -> ReverseRandomAccessCollection<(Range<Pos>)> { return (start..<end).reverse() }
所以现在我可以说:
for i in 5>>>1 {print(i)} // 4, 3, 2, 1
这只涵盖了我的代码中发生的最常见的情况,但它是最常见的情况,所以这是我目前需要的。
运营商出现了一种内部危机。 我会喜欢使用>..
,作为..<
的反向,但这不合法:你不能在一个非点之后使用一个点,它会出现。 我认为..>
但决定很难区分..<
。 关于>>>
好处是,它尖叫着你:“ 下来 ! (当然你可以自由地想出另外一个操作符,但是我的build议是:为了超级对称性,定义<<<
做什么..<
做,现在你已经有了<<<
和>>>
这是对称和易于打字。)
Swift 3版本(Xcode 8种子6):
infix operator >>> : RangeFormationPrecedence func >>><Bound>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection<CountableRange<Bound>> where Bound : Comparable, Bound.Stride : Integer { return (minimum..<maximum).reversed() }
Swift 4版本(Xcode 9 beta 3):
infix operator >>> : RangeFormationPrecedence func >>><Bound>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection<CountableRange<Bound>> where Bound : Comparable & Strideable { return (minimum..<maximum).reversed() }
看来,这个问题的答案已经改变了一点,因为我们已经通过testing。 从beta 4开始, by()
函数和ReversedRange
types都已经从该语言中删除。 如果你正在寻找一个反转的范围,你现在的select如下:
1:创build一个前进范围,然后使用reverse()
函数将其反转。
for x in reverse(0 ... 4) { println(x) // 4, 3, 2, 1, 0 } for x in reverse(0 ..< 4) { println(x) // 3, 2, 1, 0 }
2:使用beta 4中添加的新的stride()
函数,其中包括函数来指定开始和结束索引以及要迭代的数量。
for x in stride(from: 0, through: -8, by: -2) { println(x) // 0, -2, -4, -6, -8 } for x in stride(from: 6, to: -2, by: -4) { println(x) // 6, 2 }
请注意,我也在这篇文章中包含了新的独家范围的操作符。 ..
被换成..<
。
编辑:从Xcode 6 beta 5发行说明 ,苹果添加以下build议处理这个:
ReverseRange已被删除; 使用懒(x ..
这是一个例子。
for i in lazy(0...5).reverse() { // 0, 1, 2, 3, 4, 5 }
Xcode 7,testing版2:
for i in (1...5).reverse() { // do something }
在Xcode 8中 , Swift 3可以这样做:
for i in sequence(first: 10, next: {$0 - 1}) { guard i >= 0 else { break } print(i) }
结果 :10,9,8 … 0
你可以任何你喜欢的方式来定制它。 有关更多信息,请阅读func sequence<T>
参考