Nested loops

Published

2023-07-31

Nested loops

It’s not uncommon that we include one loop within another. This is called nesting, and such loops are called nested loops.

Let’s say we wanted to print out pairings of contestants in a round robin chess tournament (a “round robin” tournament is one in which each player plays each other player). Because in chess white has a slight advantage over black, it’s fair that each player should play each other player twice: once as black and once as white.

We’ll represent each game with the names of the players, in pairs, where the first player listed plays white and the second plays black.

So in a tiny tournament with players Anne, Bojan, Carlos, and Doris, we’d have the pairings:

Anne (W) vs Bojan (B)
Anne (W) vs Carlos (B)
Anne (W) vs Doris (B)
Bojan (W) vs Anne (B)
Bojan (W) vs Carlos (B)
Bojan (W) vs Doris (B)
Carlos (W) vs Anne (B)
Carlos (W) vs Bojan (B)
Carlos (W) vs Doris (B)
Doris (W) vs Anne (B)
Doris (W) vs Bojan (B)
Doris (W) vs Carlos (B)

(we exclude self-pairings for obvious reasons).

Given the list of players, ['Anne', 'Bojan', 'Carlos', 'Doris'], how could we write code to generate all these pairings? One way is with a nested loop.

players = ['Anne', 'Bojan', 'Carlos', 'Doris']

for white in players:
   for black in players:
       if white != black:  # exclude self-pairings
           print(f"{white} (W) vs {black} (B)")

This code, when executed, prints exactly the list of pairings shown above.

How does this work? The outer loop—for white in players:—iterates over all players, one at a time: Anne, Bojan, Carlos, and Doris. For each iteration of the outer loop, there’s an iteration of the inner loop, again: Anne, Bojan, Carlos, and Doris. If the element assigned to white in the outer loop does not equal the element assigned to black in the inner loop, we print the pairing. In this way, all possible pairings are generated.

Here’s another example—performing multiplication using a nested loop. (What follows is inefficient, and perhaps a little silly, but hopefully it illustrates the point.)

Let’s say we wanted to multiply 5 \times 7 without using the * operator. We could do this with a nested loop!

answer = 0

for _ in range(5):
    for __ in range(7):
        answer += 1
        
print(answer)   # prints 35

How many times does the outer loop execute? Five. How many times does the inner loop execute for each iteration of the outer loop? Seven. How many times do we increment answer? 5 \times 7 = 35.

Using nested loops to iterate a two-dimensional list

Yikes! What’s a two-dimensional list? A two-dimensional list is just a list containing other lists!

Let’s say we have the outcome of a game of tic-tac-toe encoded in a two-dimensional list:

game = [
    ['X', ' ', 'O'],
    ['O', 'X', 'O'],
    ['X', ' ', 'X']
]

To print this information in tabular form we can use a nested loop.

for row in game:
    for col in row:
        print(col, end='')
    print()

This prints

X O
OXO
X X

Original author: Clayton Cafiero < [given name] DOT [surname] AT uvm DOT edu >

No generative AI was used in producing this material. This was written the old-fashioned way.

This material is for free use under either the GNU Free Documentation License or the Creative Commons Attribution-ShareAlike 3.0 United States License (take your pick).