The for-in Loop and Range Operators - Images: Japanese
Hey there, everyone!
Next up, let's take a look at the 'for-in statement' and 'range operators'.
Let's jump right in with a sample.
let a = [0, 1, 2]
for i in a {
print(i)
}
This is the for-in statement. Here's what the output looks like.
0 1 2
The loop runs once for each element in the array 'a'. That's the 'for-in statement' — a syntax for running loop operations.
Let's go through the syntax in detail.
First, you write for, then right next to it you write any identifier you like. In the example above, that's i. Any name that's valid as a Swift identifier works here.
One thing to note: this identifier is treated as a constant. It works the same as an identifier declared with 'let', so you can't overwrite 'i' like in the example below.
let a = [0, 1, 2]
for i in a {
i = 100 // 'i' is a constant, so you can't overwrite it.
print(i)
}
Also, you can't write 'let' or 'var' after 'for'. This is another easy mistake to make, so watch out.
let a = [0, 1, 2]
for let i in a { // Writing 'let' or 'var' after 'for' is not allowed.
print(i)
}
After writing your identifier, you write 'in', and right next to that you put an array, dictionary, or similar. The loop runs once for each element. Then you write '{}' and put the code you want to run inside it.
let a = [0, 1, 2]
for i in a { // Loops once for each element in the array 'a'.
print(i) // Put the code you want to run inside the '{}'.
}
That covers the basic syntax. Now let's look at what actually ends up in the constant you wrote next to 'for'.
First, let's look at looping over an array. When you use a 'for-in statement' with an array, each element gets stored in the constant one by one as the loop runs.
let a = [0, 1, 2]
for i in a {
print(i)
}
0 1 2
Next, let's look at looping over a dictionary. It works a little differently, so let's go through that too. Looping over a dictionary looks like this.
let d = [
"Miku": "080xxxxyyyy",
"Lily": "090xxxxyyyy",
]
for t in d {
print(t)
}
Here's the output.
("Lily", "090xxxxyyyy")
("Miku", "080xxxxyyyy")
It looks like the key and value are packed inside '()'. So what are those '()' for? They're tuple parentheses. When you use a 'for-in statement' with a dictionary, the constant holds a tuple each iteration.
* For more on tuples, check out this article.
So if you want to print each key and value separately in the example above, you'd write it like this.
let d = [
"Miku": "080xxxxyyyy",
"Lily": "090xxxxyyyy",
]
for t in d {
print(t.0) // Prints the key.
print(t.1) // Prints the value.
}
The key part here is using constantName.0 and constantName.1.
That said, writing constantName.0 and constantName.1 makes it a bit hard to tell what you're actually accessing. So the common approach when looping over a dictionary is to write it like this instead.
let d = [
"Miku": "080xxxxyyyy",
"Lily": "090xxxxyyyy",
]
for (key, val) in d {
print(key) // Prints the key.
print(val) // Prints the value.
}
Notice that a tuple '(key, val)' is written where you'd normally put the constant in the 'for-in statement'. When looping over a dictionary, receiving the result as a tuple like this makes things much clearer. Just keep in mind that the first element of the tuple holds the key, and the second holds the value.
There's also a 'for statement' that can perform loops just like the 'for-in statement'. It looks like this.
for var i = 0; i < 10; ++i {
// code goes here
}
This syntax has been around since the C language era, so if you've been programming since the old days you've probably used it a lot.
However, this for statement is completely gone in modern Swift. It used to work, but now it's off the table entirely. A bit of a bummer, but that's how it goes.
So for loop operations, use the for-in statement in all cases.
Now, here's a handy technique. When looping over an array or dictionary, you might want to know which iteration you're on — "is this the 1st loop? the 2nd?"
In that case, try this approach.
let d = [
"Miku": "080xxxxyyyy",
"Lily": "090xxxxyyyy",
]
var i = 0 // Define a variable to track which iteration we're on. Initial value is '0'.
for (key, val) in d {
print(i) // Prints which iteration we're currently on.
print(key) // Prints the key.
print(val) // Prints the value.
i = i + 1 // Add '1' each time the loop runs.
}
The key is defining an Int variable outside the 'for-in statement' and incrementing it by 1 inside the loop. This is a common pattern worth remembering. Also, note that decrement operators like '++i' are deprecated in Swift, so watch out for that.
Now let's look at a different pattern of 'for-in statement'. All the samples we've covered so far have been based on looping over arrays or dictionaries.
So what do you do when you want to loop a specific number of times? You do this.
for i in 0...2 {
print(i)
}
Here's the output.
0 1 2
A total of 3 iterations run.
Take a look at the '...' in 0...2 written next to in. This is called a range operator, and writing 0...2 like this loops through 0, 1, and 2.
So if you want to loop 100 times, you'd write it like this.
for i in 0...99 { // Loops a total of 100 times.
print(i)
}
One thing to be careful about: since we're starting from '0', running 100 iterations means writing '0...99'. Easy to get wrong, so keep that in mind.
There's also another range operator '..<' that works similarly to '...', but with one difference — it doesn't include the last number. Take a look at the sample below.
for i in 0..<2 {
print(i)
}
This is the same as the earlier sample but with ... changed to ..<. Here's the output.
0 1
Unlike before, '2' at the end doesn't appear. Using '..<' gives you a range that excludes the last number.
To put it in terms of numbers a and b: a...b means a range from a up to and including b, while a..<b means a range from a up to but not including b.
By the way, ... is sometimes called the closed range operator and ..< the half-open range operator, but these terms don't come up that often so you probably don't need to memorize them.
Now let's go over a few things to watch out for when using range operators. First, the operands on either side of a range operator must be integers.
for i in 0...2.0 { // This is an error.
print(i)
}
Negative integers are fine though, since they're still integers.
for i in -2...2 { // This is OK.
print(i)
}
Also, if you have numbers a and b, the condition a <= b must hold, or you'll get an error.
for i in 3...2 { // This is an error.
print(i)
}
for i in 3..<3 { // Same numbers are OK.
print(i)
}
for i in 3..<3 { // Same numbers are OK.
print(i)
}
As long as those conditions are met, you can also use constants or variables as the operands of a range operator.
let n = 1, _n = 3
for i in n..._n {
print(i)
}
That covers the main things to watch out for with range operators. Since they're often used together with 'for-in statements', make sure you've got both down solid.
Sometimes when looping with a 'for-in statement', you don't actually use the constant written next to 'for' anywhere inside the loop.
For example, something like this.
let a = [0, 1, 2]
for i in a {
print("I love cats!")
}
In the code above, the constant i defined in the for-in statement is never used at all. In cases like this, using _ is the cleaner approach.
let a = [0, 1, 2]
for _ in a { // When you don't use the constant inside the loop body, use '_' instead.
print("I love cats!")
}
There are plenty of situations where you loop over some data but don't actually use the data itself in the loop body. In those cases, go ahead and use '_' like shown above.
And that wraps up the 'for-in statement' and 'range operators'. In the next article, we'll cover the 'while statement' and 'do-while statement'. See you there!
This article was written by Sakurama.
Author's beloved small mammal |
桜舞 春人 Sakurama HarutoA Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him. |
If you find any errors or copyright issues, please contact us.