当我在Playground中使用for循环时,一切都很好,直到我将for循环的第一个参数更改为最大值。(按降序迭代)

这是一个bug吗?还有其他人有吗?

for index in 510..509
{
    var a = 10
}

显示将要执行的迭代次数的计数器一直在滴答作响……


当前回答

使用Swift 5,根据您的需要,您可以选择以下四个Playground代码示例中的一个来解决您的问题。


# 1。使用ClosedRange reversed()方法

ClosedRange有一个叫做reversed()的方法。Reversed()方法有以下声明:

func reversed() -> ReversedCollection<ClosedRange<Bound>>

返回以相反顺序显示集合元素的视图。

用法:

let reversedCollection = (0 ... 5).reversed()

for index in reversedCollection {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

作为替代,你可以使用Range reversed()方法:

let reversedCollection = (0 ..< 6).reversed()

for index in reversedCollection {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

# 2。使用sequence(first:next:)函数

Swift标准库提供了一个名为sequence(first:next:)的函数。Sequence (first:next:)有如下声明:

func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldFirstSequence<T>

返回由first和next的重复惰性应用程序形成的序列。

用法:

let unfoldSequence = sequence(first: 5, next: {
    $0 > 0 ? $0 - 1 : nil
})

for index in unfoldSequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

# 3。使用stride(from:through:by:)函数

Swift标准库提供了一个名为stride(from:through:by:)的函数。Stride (from:through:by:)有如下声明:

func stride<T>(from start: T, through end: T, by stride: T.Stride) -> StrideThrough<T> where T : Strideable

返回一个序列,从起始值开始,并可能包括结束值,按指定的量步进。

用法:

let sequence = stride(from: 5, through: 0, by: -1)

for index in sequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

作为替代,你可以使用stride(from:to:by:):

let sequence = stride(from: 5, to: -1, by: -1)

for index in sequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

# 4。使用AnyIterator init(_:)初始化器

AnyIterator有一个名为init(_:)的初始化式。Init(_:)有如下声明:

init(_ body: @escaping () -> AnyIterator<Element>.Element?)

创建一个迭代器,将给定的闭包包装在它的next()方法中。

用法:

var index = 5

guard index >= 0 else { fatalError("index must be positive or equal to zero") }

let iterator = AnyIterator({ () -> Int? in
    defer { index = index - 1 }
    return index >= 0 ? index : nil
})

for index in iterator {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

如果需要,你可以通过为Int创建一个扩展方法并在其中包装迭代器来重构前面的代码:

extension Int {

    func iterateDownTo(_ endIndex: Int) -> AnyIterator<Int> {
        var index = self
        guard index >= endIndex else { fatalError("self must be greater than or equal to endIndex") }

        let iterator = AnyIterator { () -> Int? in
            defer { index = index - 1 }
            return index >= endIndex ? index : nil
        }
        return iterator
    }

}

let iterator = 5.iterateDownTo(0)

for index in iterator {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

其他回答

至于Swift 2.2, Xcode 7.3(2016年6月10日):

for (index,number) in (0...10).enumerate() {
    print("index \(index) , number \(number)")
}

for (index,number) in (0...10).reverse().enumerate() {
    print("index \(index) , number \(number)")
}

输出:

index 0 , number 0
index 1 , number 1
index 2 , number 2
index 3 , number 3
index 4 , number 4
index 5 , number 5
index 6 , number 6
index 7 , number 7
index 8 , number 8
index 9 , number 9
index 10 , number 10


index 0 , number 10
index 1 , number 9
index 2 , number 8
index 3 , number 7
index 4 , number 6
index 5 , number 5
index 6 , number 4
index 7 , number 3
index 8 , number 2
index 9 , number 1
index 10 , number 0

Swift向前

for i in stride(from: 5, to: 0, by: -1) {
    print(i)
}
//prints 5, 4, 3, 2, 1

for i in stride(from: 5, through: 0, by: -1) {
    print(i)
}
//prints 5, 4, 3, 2, 1, 0

对我来说,这是最好的办法。

var arrayOfNums = [1,4,5,68,9,10]

for i in 0..<arrayOfNums.count {
    print(arrayOfNums[arrayOfNums.count - i - 1])
}

对范围应用reverse函数进行反向迭代:

对于Swift 1.2及更早版本:

// Print 10 through 1
for i in reverse(1...10) {
    println(i)
}

它也适用于半开放范围:

// Print 9 through 1
for i in reverse(1..<10) {
    println(i)
}

注意:reverse(1…10)创建了一个类型为[Int]的数组,所以虽然这可能适用于较小的范围,但明智的做法是如下所示使用lazy,或者如果您的范围很大,则考虑接受的stride答案。


为了避免创建大数组,请使用lazy和reverse()。下面的测试在Playground中高效运行,显示它没有创建一个包含一万亿int的数组!

测试:

var count = 0
for i in lazy(1...1_000_000_000_000).reverse() {
    if ++count > 5 {
        break
    }
    println(i)
}

对于Xcode 7中的Swift 2.0:

for i in (1...10).reverse() {
    print(i)
}

注意,在Swift 2.0中,(1…1_000_000_000_000).reverse()的类型是ReverseRandomAccessCollection<(Range<Int>)>,所以这工作正常:

var count = 0
for i in (1...1_000_000_000_000).reverse() {
    count += 1
    if count > 5 {
        break
    }
    print(i)
}

对于Swift 3.0, reverse()已重命名为reversed():

for i in (1...10).reversed() {
    print(i) // prints 10 through 1
}

您可以使用reversed()方法轻松反转值。

var i:Int
for i in 1..10.reversed() {
    print(i)
}

reversed()方法反转值。