Start learning free

LESSON 189 OF 415 · NESTED LOOPS

Nested Loops in Swift: Rows, Columns and break

Lesson Read the full explanation

A nested loop has one loop inside of another. These are typically used for working with two dimensions such as printing stars in rows and columns as shown below. When a loop is nested inside another loop, the inner loop runs many times inside the outer loop. In each iteration of the outer loop, the inner loop will be re-started. The inner loop must finish all of its iterations before the outer loop can continue to its next iteration.

Example:

for row in 0..<3 {
	for col in 0..<5 {
		print("*", terminator: "")
	}
    print()
}

// This code prints a rectangle with 3 rows and 5 columns, filled with '*'

Iterating through multidimensional arrays

Nested loops are also helpful when we want to iterate through a multi dimensional array, for example:

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 outputs each sub-element in arr one at a time. Note that for the inner loop, we are checking the .count of arr[i], since arr[i] is itself an array.

Breaking nested loops

In a nested loop, a break statement only stops the loop it is placed in. Therefore, if a break is placed in the inner loop, the outer loop still continues. For example:

let arr = [[1, 2], [3, 4], [5, 6]]

for i in 0..<arr.count {
	for j in 0..<arr[i].count {
		if arr[i][j] == 3 {
			break
		}
		print(arr[i][j])
	}
}

// prints the numbers 1, 2, 5 and 6 on different lines

When i is 1 and j is 0, we execute the break. This means we stop the inner loop and go back to the outer loop to continue from the next iteration, which is i = 2. And as you can see, we print all the elements of row 2.

However, if the break is placed in the outer loop, all of the looping stops. For example:

let arr = [[1, 2], [3, 4], [5, 6]]

for i in 0..<arr.count {
	if arr[i][0] == 3 {
		break
	}
	for j in 0..<arr[i].count {
		print(arr[i][j])
	}
}
// prints the numbers 1 and 2 on different lines

Assignment
Follow the Coding Tutorial and let's write some nested loops.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 4
    Ctrl + Enter to check

    SWIFT · NESTED LOOPS

    Nested Loops in Swift, explained

    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:

    1. The outer loop. 0..<5 is a half-open range: it includes 0 and leaves out 5, so row takes the five values 0 to 4.
    2. The inner loop. Written inside the outer one, 0..<10 gives ten passes for every row.
    3. The star. print normally ends its output with a newline. The terminator argument replaces that ending, and an empty string keeps the next star on the same line.
    4. 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].count is the right bound for the inner loop, not arr[0].count.
    • Mixing up the range operators. 0..<5 stops before 5 and 0...5 includes 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, and print() ends the line.
    • For an array of arrays, bound the inner loop by arr[i].count.
    • A plain break affects only its own loop. A labeled break, such as break outer, can leave several.
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free