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开始, byReverseRange不存在了:[

如果你只是想扭转一个范围, 反向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()函数和ReversedRangetypes都已经从该语言中删除。 如果你正在寻找一个反转的范围,你现在的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>参考