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.
Apply the reverse function to the range to iterate backwards:
For Swift 1.2 and earlier:
// Print 10 through 1
for i in reverse(1...10) {
println(i)
}
It also works with half-open ranges:
// Print 9 through 1
for i in reverse(1..<10) {
println(i)
}
Note: reverse(1...10) creates an array of type [Int], so while this might be fine for small ranges, it would be wise to use lazy as shown below or consider the accepted stride answer if your range is large.
To avoid creating a large array, use lazy along with reverse(). The following test runs efficiently in a Playground showing it is not creating an array with one trillion Ints!
Test:
var count = 0
for i in lazy(1...1_000_000_000_000).reverse() {
if ++count > 5 {
break
}
println(i)
}
For Swift 2.0 in Xcode 7:
for i in (1...10).reverse() {
print(i)
}
Note that in Swift 2.0, (1...1_000_000_000_000).reverse() is of type ReverseRandomAccessCollection<(Range<Int>)>, so this works fine:
var count = 0
for i in (1...1_000_000_000_000).reverse() {
count += 1
if count > 5 {
break
}
print(i)
}
For Swift 3.0 reverse() has been renamed to reversed():
for i in (1...10).reversed() {
print(i) // prints 10 through 1
}
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 rangeForward
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 indexSometimes 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 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.
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
@matt has an interesting solution where he defines his own reverse operator and calls it >>>. It doesn't take much code to define and is used like this:
for index in 5>>>0 {
print(index)
}
// 4
// 3
// 2
// 1
// 0
Check out On C-Style For Loops Removed from Swift 3
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With