What a nested loop is
A nested loop is a loop inside another loop. The outer loop starts one pass, and the inner loop then runs from start to finish before the outer loop moves on to its next pass. On each new outer pass the inner loop starts over.
That makes nested loops the natural tool for anything with two dimensions: rows and columns of a picture, a table, an array of arrays, or every pair of elements in a collection.
The syntax
In Scala a for loop over a range reads "for each value in this range". 0 until 3 gives 0, 1 and 2 and leaves out the upper end, while 0 to 3 includes 3.
for (row <- 0 until 3) {
for (col <- 0 until 5) {
print("*")
}
println()
}
*****
*****
*****
The pieces:
print("*")writes text and stays on the same line.println()with no argument ends the current line.- The inner loop's closing brace comes before
println(), so a newline is printed once per row and not once per star.
The inner body runs 3 × 5 = 15 times in total. In general, if the outer loop runs a times and the inner loop runs b times per pass, the inner body runs a * b times. This count is what makes nested loops costly on large inputs.
The inner range can depend on the outer variable
The inner loop doesn't have to run the same number of times on every pass:
for (row <- 1 to 4) {
for (col <- 1 to row) {
print("*")
}
println()
}
*
**
***
****
Looping through an array of arrays
A two-dimensional array in Scala is an array whose elements are arrays. Elements are read with parentheses, not square brackets:
val arr = Array(Array(1, 2), Array(3, 4), Array(5, 6))
for (i <- arr.indices) {
for (j <- arr(i).indices) {
println(arr(i)(j))
}
}
This prints 1, 2, 3, 4, 5 and 6, one per line. arr.indices is the range of valid positions, 0 until arr.length. The inner loop uses arr(i).indices because arr(i) is itself an array, and rows may have different lengths. arr(i)(j) picks row i, then element j inside it.
Skipping values and stopping early
To skip some elements, put the work behind an if:
for (i <- arr.indices) {
for (j <- arr(i).indices) {
if (arr(i)(j) != 3 && arr(i)(j) != 4) {
println(arr(i)(j))
}
}
}
This prints 1, 2, 5 and 6. When the value is 3 or 4 the condition is false, so the body is skipped, but both loops continue.
Scala has no break statement in the language itself. If you need to stop a loop early, the usual approach is a while loop with a flag you check in its condition. The standard library also has scala.util.control.Breaks, with breakable and break(), but you won't need it in this lesson.
Several loops in one for
Scala can put both ranges into a single for, separated by a semicolon:
for (r <- 1 to 3; c <- 1 to 3) {
print(r * c + " ")
}
This prints 1 2 3 2 4 6 3 6 9 . It is the same as nesting two loops, with the second changing fastest. A separate nested loop is still the clearer choice when you need something to happen after the inner loop, such as the println() above.
The exercise, step by step
The task is to print a rectangle of stars with 5 rows and 10 columns.
- The outer loop. Write
for (row <- 0 until 5). One pass per row, and0 until 5gives the five values 0 to 4. - The inner loop. Inside it, write
for (col <- 0 until 10). One pass per column. Its body will run 5 × 10 = 50 times. - Print a star. Inside the inner loop, call
print("*"), with no newline, so the 10 stars of one row share a line. - End the row. After the inner loop but still inside the outer one, call
println(). The next row starts on a new line.
for (row <- 0 until 5) {
for (col <- 0 until 10) {
print("*")
}
println()
}
The output is five lines of ten stars:
**********
**********
**********
**********
**********
Common mistakes
- Putting
println()inside the inner loop. Every star lands on its own line, giving 50 lines with one star each. - Leaving
println()out. All 50 stars end up on one line. - Mixing up
untilandto.0 until 5runs 5 times;0 to 5runs 6 times. - Reusing one variable name. Naming both loop variables
ihides the outer one inside the inner loop. Use distinct names such asrowandcol. - Using square brackets.
arr[i][j]doesn't work in Scala; writearr(i)(j).
Key takeaways
- The inner loop runs completely on every pass of the outer loop, so the inner body runs
outer * innertimes. printkeeps the line open andprintln()ends it.- For an array of arrays, loop over
arr.indicesand thenarr(i).indices, and read elements asarr(i)(j).
