Looping Patterns With For Loops

When using for loops, a few patterns show up frequently. If you learn these patterns — how to recognize them and how to code them — it can help you translate problems into code more easily.

The Action Pattern

In the action pattern, we want to do something to (or with) each element of a list. This is the easiest pattern, because we can treat each item independently. All we need is a loop:

for each x in xx:
    do something using x

Example: Printing the Elements of a List

for x in xx:
    print(x)

Example: Printing the Elements of a List and Their Squares

for x in xx:
    print(f"{x}, {x*x}")

The Accumulator Pattern

Unfortunately, most of the times we work with lists, we want to combine their items in some way. In the accumulator pattern, we want to build up a pattern using a collection of data.

Here is the pseudocode template:

initialize the accumulator
for each x in xx:
    modify accumulator using x

(the final result is in accumulator)

The two tricky parts about the accumulator pattern are what to choose as the initial value for the accumulator, and how to update it. Here are two rules of thumb that can help you get started:

  1. When initializing the accumulator, think about what the result should be if the list was empty. In fact, if the list is empty, the for loop will be skipped, so the accumulator will be whatever you initialized it as. Common initial values are 0, [] or "", but you might have to be more careful, for example when you multiply numbers and don’t want to multiply with 0.

Example: Counting the Elements of a List

For this, count is the accumulator, and at each step we add one to it.

count = 0
for x in xx:
    count = count + 1

Example: Summing the Elements of a List

For this, sum is the accumulator, and at each step we add x to it.

sum = 0
for x in xx:
    sum = sum + x

Example: Create a Dictionary with the Elements of a List and Their Squares

For this, d is the accumulator, and at each step we update it by inserting key x with value x*x.

d = {}
for x in xx:
    d[x] = x * x

Example: Taking the Maximum of the Elements of a List

For this, themax is the accumulator, and at each step we update it with x using the built-in function max.

themax = xx[0]
for x in xx:
    themax = max(themax,x)

Note that here initializing themax is tricky, because the maximum of an empty list doesn’t really make sense. We initialize it to the first element of the list, which requires that the list is non-empty. If the list is empty, the code above will produce an error. You could also initialize themax with some arbitrary number like 0 or -99999999, but that can also be dangerous, for example when the list only contains only numbers that are even smaller.

The Accumulator Pattern with Logic

Sometimes, we don’t just want to combine the elements of a list, but also treat them differently depending on their value. This is where the accumulator pattern needs to be combined with some logic:

initialize the accumulator
for each x in xx:
    if some condition:
        modify accumulator using x
    else (optional):
        modify accumulator in a different way

(the final result is in accumulator)

Example: Keeping only Elements of a List Greater than 0

For this, filtered is the accumulator, and at each step we only append x if it is greater than 0.

filtered = []
for x in xx:
    if x > 0:
        filtered.append(x)

Example: Summing only Even Elements of a List

For this, sum is the accumulator, and at each step we only add x if it is even. Note that we can check if x is even by writing x % 2 == 0 (read: “if we do integer division of x by 2, is the remainder 0?”).

sum = 0
for x in xx:
    if x % 2 == 0:
        sum = sum + x

Example: Taking the Maximum of the Elements of a List, Alternative Approach

For this, themax is again the accumulator, but this time we do not use the built-in function max. Instead, we use our own logic.

themax = xx[0]
for x in xx:
    if x > themax:
        themax = x