斯威夫特的反向范围

有没有办法在 Swift 中使用反向范围?

例如:

for i in 5...1 {
// do something
}

是一个无限循环。

在新版本的 Swift 中,代码会被编译,但在运行时会出现错误:

致命错误: 不能用上界 < 下界形成 Range

我知道我可以使用 1..5代替,计算 j = 6 - i和使用 j作为我的索引。我只是想知道还有什么更清晰的吗?

41198 次浏览

更新最新的 Swift 3(仍然在 Swift 4中工作)

You can use the reversed() method on a range

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 has been reworked in Xcode 7 Beta 6. The new usage is:

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开始,作者反向范围就不再存在了:

If you are just looking to reverse a range, the 倒车 function is all you need:

for i in reverse(1...5) { println(i) } // prints 5,4,3,2,1

根据 第一季,第7集提供的信息,有一个新的 跨步结构,它可以用来对任意整数进行迭代和增量。苹果还表示,浮点支持即将到来。

来源于他的回答:

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
}

It appears that the answers to this question have changed a bit as we've progressed through the betas. As of beta 4, both the by() function and the ReversedRange type have been removed from the language. If you're looking to make a reversed range, your options are now as follows:

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版本说明,苹果增加了以下处理建议:

反向范围已被删除; 请使用惰性(x。

举个例子。

for i in lazy(0...5).reverse() {
// 0, 1, 2, 3, 4, 5
}

Xcode 7,beta 2 (< Swift 3.0):

for i in (1...5).reverse() {
// do something
}

Xcode 8.0 + (Swift 3.0+)的更新,每个 开发人员文档,截至2020年12月8日可用:

  • 对于 反向迭代集合,在不更改集合内容的情况下,使用 reversed-
let word = "Backwards"
for char in word.reversed() {
print(char, terminator: "")
}
// Prints "sdrawkcaB"

In this case, a wrapper around the collection reads the collection's contents and returns them in reverse order.

  • 对于 反转收藏品的内容,使用类型初始值设定项,并为其提供集合 reversed。这使得一个新的收藏具有相同的内容,但相反:
let reversedWord = String(word.reversed())
print(reversedWord)
// Prints "sdrawkcaB"
  • 另外,可以使用泛型函数 stride(from:to:by:)反向返回集合的内容(以及正常顺序) :
for countdown in stride(from: 3, to: 0, by: -1) {
print("\(countdown)...")
}
// 3...
// 2...
// 1...

If the from value is higher than the to value, and the by value is negative, stride reads contents in reverse.

If the from value is lower than the to value, and the by value is positive, stride will read through the contents in their original order.

Note: Collections include arrays, sets, dictionaries, as well as other specialized collections. As long as the collection is iterable, these techniques will work.

第二注: 截至2020年12月8日,Swift 版本及其相关的 Xcode 版本可以在 https://swiftly.dev/swift-versions上找到。根据这个参考文献,Xcode 8.0 + 与 Swift 3.0相关联,也就是 reverse()变成 reversed()的时候。

这种不对称性有些令人不安的地方:

for i in (1..<5).reverse()

而不是这样:

for i in 1..<5 {

这意味着,每次我想做一个反向范围,我必须记住把括号,加上我必须写在结束 .reverse(),突出像一个酸痛的拇指。与 C 风格的 for 循环相比,这真的很难看,因为循环是对称的计数和倒计时。所以我倾向于使用 C 风格的 for 循环。但是在 Swift 2.2中,C 风格的 for 循环正在消失!所以我不得不用这个丑陋的 .reverse()结构替换掉所有递减的 C 风格 for 循环ーー一直在想,到底为什么没有反向范围运算符?

但是等等! 这是斯威夫特ーー我们可以定义自己的运营商! ! 我们开始吧:

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

这仅仅涵盖了在我的代码中发生的最常见的情况,但是它是 中最常见的情况,所以这就是我目前所需要的。

接线员那边出了点内部危机。我希望使用 >..,作为 ..<的反面,但这是不合法的: 你不能使用一个点后非点,它似乎。我考虑了 ..>,但认为它太难与 ..<区分开来。>>>的好处是它对你大喊: “ 放下到!”(当然,你可以自由地想出另一个操作员。但是我的建议是: 为了超对称,定义 <<<来做 ..<所做的事情,现在你已经得到了 <<<>>>,它们是对称且易于输入的。)


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()
}

Swift 4.2版本(Xcode 10 beta 1) :

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedRandomAccessCollection<Range<Bound>>
where Bound : Strideable {
return (minimum..<maximum).reversed()
}

Swift 5版本(Xcode 10.2.1) :

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedCollection<Range<Bound>>
where Bound : Strideable {
return (minimum..<maximum).reversed()
}

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>参考

This could be another way of doing this.

(1...5).reversed().forEach { print($0) }

反向()函数用于反向编号。

Var n: Int//Enter number

因为 i 在1... n. return ()中 { 打印(i) }