How to iterate for loop in reverse order in swift?

2019-01-02 17:17发布

When I use the for loop in Playground, everything worked fine, until I changed the first parameter of for loop to be the highest value. (iterated in descending order)

Is this a bug? Did any one else have it?

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

The counter that displays the number of iterations that will be executions keeps ticking...

enter image description here

13条回答
十年一品温如言
2楼-- · 2019-01-02 18:07

In Swift 4 and latter

    let count = 50//For example
    for i in (1...count).reversed() {
        print(i)
    }
查看更多
牵手、夕阳
3楼-- · 2019-01-02 18:09

You can use reversed() method for easily reverse values.

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

The reversed() method reverse the values.

查看更多
若你有天会懂
4楼-- · 2019-01-02 18:13

Xcode 6 beta 4 added two functions to iterate on ranges with a step other than one: stride(from: to: by:), which is used with exclusive ranges and stride(from: through: by:), which is used with inclusive ranges.

To iterate on a range in reverse order, they can be used as below:

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

Note that neither of those is a Range member function. They are global functions that return either a StrideTo or a StrideThrough struct, which are defined differently from the Range struct.

A previous version of this answer used the by() member function of the Range struct, which was removed in beta 4. If you want to see how that worked, check the edit history.

查看更多
深知你不懂我心
5楼-- · 2019-01-02 18:15

With Swift 3, according to your needs, you may choose one of the eight following Playground code implementations in order to solve your problem.


#1. Using CountableClosedRange reversed() method

CountableClosedRange has a method called reversed(). reversed() method has the following declaration:

func reversed() -> ReversedRandomAccessCollection<CountableClosedRange<Bound>>

Returns a view presenting the elements of the collection in reverse order.

Usage:

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

for index in reversedRandomAccessCollection {
    print(index)
}

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

#2. Using CountableRange reversed() method

CountableRange has a method called reversed(). reversed() method has the following declaration:

func reversed() -> ReversedRandomAccessCollection<CountableRange<Bound>>

Returns a view presenting the elements of the collection in reverse order.

Usage:

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

for index in reversedRandomAccessCollection {
    print(index)
}

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

#3. Using sequence(first:next:) function

Swift Standard Library provides a function called sequence(first:next:). sequence(first:next:) has the following declaration:

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

Returns a sequence formed from first and repeated lazy applications of next.

Usage:

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

for index in unfoldSequence {
    print(index)
}

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

#4. Using stride(from:through:by:) function

Swift Standard Library provides a function called stride(from:through:by:). stride(from:through:by:) has the following declaration:

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

Returns the sequence of values (self, self + stride, self + 2 * stride, … last) where last is the last value in the progression less than or equal to end.

Usage:

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

for index in sequence {
    print(index)
}

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

#5. Using stride(from:to:by:) function

Swift Standard Library provides a function called stride(from:to:by:). stride(from:to:by:) has the following declaration:

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

Returns the sequence of values (self, self + stride, self + 2 * stride, … last) where last is the last value in the progression that is less than end.

Usage:

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

for index in sequence {
    print(index)
}

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

#6. Using AnyIterator init(_:) initializer

AnyIterator has an initializer called init(_:). init(_:) has the following declaration:

init<I>(_ base: I) where I : IteratorProtocol, I.Element == Element

Creates an iterator that wraps a base iterator but whose type depends only on the base iterator’s element type.

Usage:

var index = 5

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

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

for index in iterator {
    print(index)
}

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

#7. Using AnyIterator init(_:) initializer

AnyIterator has an initializer called init(_:). init(_:) has the following declaration:

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

Creates an iterator that wraps the given closure in its next() method.

Usage:

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

#8. Using a custom Int extension method

You can refactor the previous code by creating an extension method for Int and wrapping your iterator in it:

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楼-- · 2019-01-02 18:17

Updated for Swift 3

The answer below is a summary of the available options. Choose the one that best fits your needs.

reversed: numbers in a range

Forward

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

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

Backward

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

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

reversed: elements in SequenceType

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

Forward

for animal in animals {
    print(animal)
}

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

Backward

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

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

reversed: elements with an index

Sometimes an index is needed when iterating through a collection. For that you can use enumerate(), which returns a tuple. The first element of the tuple is the index and the second element is the object.

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

Forward

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

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

Backward

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

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

Note that as Ben Lachman noted in his answer, you probably want to do .enumerated().reversed() rather than .reversed().enumerated() (which would make the index numbers increase).

stride: numbers

Stride is way to iterate without using a range. There are two forms. The comments at the end of the code show what the range version would be (assuming the increment size is 1).

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

Forward

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

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

Backward

Changing the increment size to -1 allows you to go backward.

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

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

Note the to and through difference.

stride: elements of SequenceType

Forward by increments of 2

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

I'm using 2 in this example just to show another possibility.

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

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

Backward

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

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

Notes

查看更多
皆成旧梦
7楼-- · 2019-01-02 18:17

Swift 4 onwards

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
查看更多
登录 后发表回答