有没有办法在Swift中使用反向范围?
例如:
for i in 5...1 {
// do something
}
是一个无限循环。
我知道我可以使用1..5
来计算j = 6 - i
并使用j
作为我的索引。我只是想知道是否有更清晰的东西?
答案 0 :(得分:160)
更新最新的Swift 3(仍可在Swift 4中使用)
您可以在范围
上使用reversed()
方法
for i in (1...5).reversed() { print(i) } // 5 4 3 2 1
或stride(from:through:by:)
方法
for i in stride(from:5,through:1,by:-1) { print(i) } // 5 4 3 2 1
stide(from:to:by:)
类似,但不包括最后一个值
for i in stride(from:5,to:0,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中重新设计。新用法是:
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开始, 和 ReverseRange 不再存在:[
如果您只想反转一个范围,只需反向功能:
for i in reverse(1...5) { println(i) } // prints 5,4,3,2,1
由 0x7fffffff 发布时,有一个新的 stride 结构,可用于通过任意整数进行迭代和递增。 Apple还表示将支持浮点支持。
来自他的回答:
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
}
答案 1 :(得分:19)
这种不对称有些令人不安:
for i in (1..<5).reverse()
......而不是:
for i in 1..<5 {
这意味着每次我想做一个反向范围时,我都要记得把括号括起来,而且我必须在最后写.reverse()
,像拇指一样伸出来。与C风格的for循环相比,这是非常难看的,它们是对称计数和倒计时。所以我倾向于使用C风格的循环代替。但是在Swift 2.2中,C风格的for循环正在消失!所以我不得不匆匆忙忙用这个丑陋的.reverse()
构造来替换我所有递减的C风格for循环 - 一直想知道,为什么地球上没有反向范围算子呢?
但是等等!这是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
这仅涵盖我的代码中最常见的情况,但 远离最常见的情况,所以这就是我目前所需要的。
我遇到了运营商的内部危机。我本来希望使用>..
,因为它与..<
相反,但这不合法:看起来,你不能在非点之后使用点。我考虑过..>
,但认为很难区分..<
。关于>>>
的好处是它尖叫着你:“ down to!” (当然你可以自由地想出另一个算子。但我的建议是:对于超对称,定义<<<
来做..<
做的事,现在你已经<<<
和>>>
对称且易于输入。)
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound) ->
ReversedRandomAccessCollection<CountableRange<Bound>>
where Bound : Comparable, Bound.Stride : Integer {
return (minimum..<maximum).reversed()
}
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedRandomAccessCollection<CountableRange<Bound>>
where Bound : Comparable & Strideable {
return (minimum..<maximum).reversed()
}
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedRandomAccessCollection<Range<Bound>>
where Bound : Strideable {
return (minimum..<maximum).reversed()
}
答案 2 :(得分:9)
看来这个问题的答案已经发生了一些变化,因为我们已经通过了测试版。从测试版4开始,by()
函数和ReversedRange
类型都已从语言中删除。如果您希望制作相反的范围,您的选项现在如下:
1:创建一个前向范围,然后使用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 release notes中,Apple添加了以下建议来处理此问题:
ReverseRange已被删除;使用懒惰(x ..
这是一个例子。
for i in lazy(0...5).reverse() {
// 0, 1, 2, 3, 4, 5
}
答案 3 :(得分:5)
Xcode 7,beta 2:
for i in (1...5).reverse() {
// do something
}
答案 4 :(得分:3)
Swift 3,4 + :你可以这样做:
for i in sequence(first: 10, next: {$0 - 1}) {
guard i >= 0 else {
break
}
print(i)
}
结果:10,9,8 ... 0
您可以根据自己的喜好自定义它。有关详情,请阅读func sequence<T>
reference
答案 5 :(得分:0)
这可能是另一种方法。
(1...5).reversed().forEach { print($0) }
答案 6 :(得分:-1)
Reverse()函数用于反向编号。
变量n:Int //输入数字
对于1中的i ... n.reverse() { 打印(i) }