如何在swift中以相反的顺序迭代循环?

时间:2014-07-01 10:59:32

标签: ios swift swift-playground

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

这是一个错误吗?还有其他人有吗?

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

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

enter image description here

15 个答案:

答案 0 :(得分:199)

将反向函数应用于范围以向后迭代:

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如下所示是明智的,或者考虑接受{ {1}}如果您的范围很大,请回答。


要避免创建大型数组,请使用stridelazy。以下测试在Playground中高效运行,表明它没有创建一个万亿reverse()秒的数组!

<强>测试

Int

对于Xcode 7中的 Swift 2.0

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

请注意,在Swift 2.0中,for i in (1...10).reverse() { print(i) } 的类型为(1...1_000_000_000_000).reverse(),因此效果正常:

ReverseRandomAccessCollection<(Range<Int>)>

Swift 3.0 var count = 0 for i in (1...1_000_000_000_000).reverse() { count += 1 if count > 5 { break } print(i) } 已重命名为reverse()

reversed()

答案 1 :(得分:181)

Xcode 6 beta 4添加了两个函数来迭代范围而不是一个步骤: stride(from: to: by:),与排他范围和stride(from: through: by:)一起使用,与包含范围一起使用。

要以相反的顺序迭代一个范围,可以按如下方式使用它们:

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

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

请注意,这些都不是Range成员函数。它们是返回StrideToStrideThrough结构的全局函数,它们的定义与Range结构不同。

此答案的先前版本使用by()结构的Range成员函数,该结果已在测试版4中删除。如果您想了解其工作原理,请查看编辑历史记录。

答案 2 :(得分:81)

更新了Swift 3

以下答案是可用选项的摘要。选择最适合您需求的那个。

reversed:范围内的数字

转发

for index in 0..<5 {
    print(index)
}

// 0
// 1
// 2
// 3
// 4

<强>向后

for index in (0..<5).reversed() {
    print(index)
}

// 4
// 3
// 2
// 1
// 0

reversedSequenceType

中的元素
let animals = ["horse", "cow", "camel", "sheep", "goat"]

转发

for animal in animals {
    print(animal)
}

// horse
// cow
// camel
// sheep
// goat

<强>向后

for animal in animals.reversed() {
    print(animal)
}

// goat
// sheep
// camel
// cow
// horse

reversed:索引为

的元素

有时在迭代集合时需要索引。为此,您可以使用enumerate(),它返回一个元组。元组的第一个元素是索引,第二个元素是对象。

let animals = ["horse", "cow", "camel", "sheep", "goat"]

转发

for (index, animal) in animals.enumerated() {
    print("\(index), \(animal)")
}

// 0, horse
// 1, cow
// 2, camel
// 3, sheep
// 4, goat

<强>向后

for (index, animal) in animals.enumerated().reversed()  {
    print("\(index), \(animal)")
}

// 4, goat
// 3, sheep
// 2, camel
// 1, cow
// 0, horse

请注意,正如Ben {Lachman在his answer中所说,您可能希望.enumerated().reversed()而不是.reversed().enumerated()(这会使索引编号增加)。

步幅:数字

Stride是在不使用范围的情况下迭代的方法。有两种形式。代码末尾的注释显示了范围版本(假设增量大小为1)。

startIndex.stride(to: endIndex, by: incrementSize)      // startIndex..<endIndex
startIndex.stride(through: endIndex, by: incrementSize) // startIndex...endIndex

转发

for index in stride(from: 0, to: 5, by: 1) {
    print(index)
}

// 0
// 1
// 2
// 3
// 4

<强>向后

将增量大小更改为-1可让您后退。

for index in stride(from: 4, through: 0, by: -1) {
    print(index)
}

// 4
// 3
// 2
// 1
// 0

请注意tothrough之差。

stride:SequenceType

的元素

以2为增量转发

let animals = ["horse", "cow", "camel", "sheep", "goat"]

我在这个例子中使用2只是为了表明另一种可能性。

for index in stride(from: 0, to: 5, by: 2) {
    print("\(index), \(animals[index])")
}

// 0, horse
// 2, camel
// 4, goat

<强>向后

for index in stride(from: 4, through: 0, by: -1) {
    print("\(index), \(animals[index])")
}

// 4, goat
// 3, sheep 
// 2, camel
// 1, cow  
// 0, horse 

注释

答案 3 :(得分:48)

Swift 4 以后

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

答案 4 :(得分:27)

对于Swift 2.0及更高版本,您应该对范围集合应用反向

for i in (0 ..< 10).reverse() {
  // process
}

它已在Swift 3.0中重命名为.reversed()

答案 5 :(得分:20)

使用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>
  

返回由firstnext的重复延迟应用程序组成的序列。

用法:

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
*/

答案 6 :(得分:7)

在Swift 4和后者中

    let count = 50//For example
    for i in (1...count).reversed() {
        print(i)
    }

答案 7 :(得分:4)

Swift 4.0

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

如果要包含to值:

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

答案 8 :(得分:3)

如果想要反向遍历数组Array或更常见的任何SequenceType)。您还有一些其他选择。

首先,您可以reverse()数组并正常循环播放它。但是我更喜欢在{I}大部分时间使用enumerate(),因为它输出一个包含对象及其索引的元组。

这里需要注意的一点是,以正确的顺序调用这些内容非常重要:

for (index, element) in array.enumerate().reverse()

按降序生成索引(这是我通常所期望的)。而:

for (index, element) in array.reverse().enumerate()(与NSArray的reverseEnumerator更接近)

向后走数组但输出升序索引。

答案 9 :(得分:2)

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

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

答案 10 :(得分:1)

var sum1 = 0
for i in 0...100{
    sum1 += i
}
print (sum1)

for i in (10...100).reverse(){
    sum1 /= i
}
print(sum1)

答案 11 :(得分:1)

您可以考虑使用C风格while循环。这在Swift 3中运行得很好:

var i = 5 
while i > 0 { 
    print(i)
    i -= 1
}

答案 12 :(得分:1)

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

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

reverse()方法反转了值。

答案 13 :(得分:0)

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

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

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

答案 14 :(得分:-1)

如果有数组,您可以简单地执行此操作

func reverseArray(a: [Int]) -> [Int] {
   var reverseArr = [Int]()
   for i in stride(from: a.count-1, to: -1, by: -1){
      reverseArr.append(a[i])
   }
   return reverseArr
}