What a nested loop is
A nested loop is a loop inside another loop. The outer loop starts an iteration, and the inner loop then runs from start to finish. Only then does the outer loop move on, and the inner loop starts again from the beginning. If the outer loop runs 5 times and the inner loop runs 10 times per pass, the inner body runs 5 × 10 = 50 times.
Nested loops are the natural tool for anything with two dimensions: rows and columns, a table, every pair of items in a list.
Printing a rectangle of stars
The exercise prints a rectangle of 5 rows and 10 columns. The outer loop counts rows, the inner loop counts columns:
for row in 0..<5 {
for col in 0..<10 {
print("*", terminator: "")
}
print()
}
**********
**********
**********
**********
**********
Step by step:
- The outer loop.
0..<5is a half-open range: it includes 0 and leaves out 5, sorowtakes the five values 0 to 4. - The inner loop. Written inside the outer one,
0..<10gives ten passes for every row. - The star.
printnormally ends its output with a newline. Theterminatorargument replaces that ending, and an empty string keeps the next star on the same line. - The newline. A bare
print()prints just a line break. It sits after the inner loop's closing brace but still inside the outer loop, so it runs once per row. Moved inside the inner loop, it would put every star on its own line.
Neither row nor col is used in the body. Swift compiles the code and warns that the constants were never used, suggesting the underscore. Writing for _ in 0..<5 says that the count matters but the value does not. The lesson keeps the names so the loops read clearly.
The loop variables are worth using when the output depends on them. This prints a multiplication table:
for r in 1...3 {
for c in 1...3 {
print(r * c, terminator: " ")
}
print()
}
1 2 3
2 4 6
3 6 9
Here the closed range 1...3 includes both ends. Each line ends with a space, because the terminator is printed after every number.
Looping over a two-dimensional array
An array of arrays is a grid: the outer array holds rows, and each row is an array. Visiting every element takes two loops. The inner one must use the length of the current row:
let arr = [[1, 2], [3, 4], [5, 6]]
for i in 0..<arr.count {
for j in 0..<arr[i].count {
print(arr[i][j])
}
}
This prints 1 to 6, one per line. arr.count is the number of rows, arr[i].count is the number of elements in row i, and arr[i][j] reads one element. When the indices are not needed, Swift can loop over the values directly:
for row in arr {
for value in row {
print(value, terminator: " ")
}
}
This prints 1 2 3 4 5 6 on one line.
break in nested loops
A break leaves only the innermost loop that contains it. In this code the inner loop stops at the 3, and the outer loop carries on with the next row:
for i in 0..<arr.count {
for j in 0..<arr[i].count {
if arr[i][j] == 3 {
break
}
print(arr[i][j])
}
}
It prints 1, 2, 5 and 6. When i is 1 and j is 0, the 3 triggers the break, so the 4 is skipped, but row 2 is printed in full.
A break placed in the outer loop, outside the inner one, ends all the looping. This code stops before row 1 begins, so it prints only 1 and 2:
for i in 0..<arr.count {
if arr[i][0] == 3 {
break
}
for j in 0..<arr[i].count {
print(arr[i][j])
}
}
To stop both loops from inside the inner one, Swift lets you label the outer loop and name the label in break:
outer: for i in 0..<arr.count {
for j in 0..<arr[i].count {
if arr[i][j] == 3 {
break outer
}
print(arr[i][j])
}
}
This prints 1 and 2, and nothing after the 3.
Common mistakes
- Putting the newline in the wrong loop.
print()inside the inner loop gives one star per line. Missing entirely, it gives one long row of 50 stars. - Using the outer row length for every row. When rows differ in length,
arr[i].countis the right bound for the inner loop, notarr[0].count. - Mixing up the range operators.
0..<5stops before 5 and0...5includes it. The second would give six rows. - Expecting break to end both loops. Use a label when it must.
Key takeaways
- The inner loop restarts on every pass of the outer loop, so the body runs outer count times inner count.
print(x, terminator: "")keeps output on one line, andprint()ends the line.- For an array of arrays, bound the inner loop by
arr[i].count. - A plain
breakaffects only its own loop. A labeled break, such asbreak outer, can leave several.
