When a range is not enough
A range such as 2...10 always moves by 1. To count in bigger steps, for example every second number, Swift offers the stride function. It produces a sequence of numbers with a start, an end and a step, and a for-in loop can go through it:
for i in stride(from: 2, through: 10, by: 2) {
print(i)
}
The output is:
2
4
6
8
10
The three parts of stride
from: 2is the first value of the sequence, so the loop starts at 2.through: 10is the last value allowed. If the steps land exactly on 10, it is included.by: 2is the step added to the value each time.
The loop variable i takes the values 2, 4, 6, 8 and 10 in turn, the same way it would for a range.
through versus to
There are two versions of stride, and they differ in how they treat the end value:
stride(from:through:by:)includes the end value when a step lands on it.stride(from:to:by:)never includes the end value, like the half-open range..<.
With the end value 10 and a step of 2, the two behave differently:
for i in stride(from: 2, to: 10, by: 2) {
print(i, terminator: " ")
}
2 4 6 8
This stops at 8 because 10 is excluded. Writing to: 11 brings 10 back, since 11 is not reached and 10 is below it. In both versions, a step that doesn't land on the end value simply stops at the last value before it. For example, stride(from: 2, through: 9, by: 2) gives 2, 4, 6 and 8.
The exercise: odd numbers from 7 through 23
The task is to print the odd numbers between 7 and 23, with both ends included. It is built in two steps.
- Write the loop header. The first odd number is 7, and the odd numbers are 2 apart, so the start is
from: 7and the step isby: 2. The last number to print is 23, and the task says "through", so usethrough: 23. - Print
iin the body. Each pass prints the current value on its own line.
for i in stride(from: 7, through: 23, by: 2) {
print(i)
}
The values are 7, 9, 11, 13, 15, 17, 19, 21 and 23. Starting on an odd number and adding 2 each time keeps every value odd, so no check with % is needed.
Common mistakes
- Using
to:when the end must be included.stride(from: 7, to: 23, by: 2)stops at 21. - Starting on an even number. From 8 with a step of 2 every value is even, so the odd numbers never appear.
- Mixing up the labels. The labels
from:,through:(orto:) andby:are required and must come in this order. - Using a step of 0. A step of zero would never make progress, and Swift stops the program with a run-time error.
- Using a negative step to count up. With
from: 2, through: 10, by: -2the sequence is empty, because the step moves away from the end value. Counting down is covered in the next lesson.
Key takeaways
stridelets afor-inloop move in steps other than 1.through:includes the end value andto:excludes it.- Starting on an odd number and stepping by 2 visits only odd numbers.
- The step in
by:must not be 0.
