Grade by Grade
A. Programming Concepts and Skills · Arrays and Subprograms

Traversing a List: Counting, Totals and Averages

A2.3 A1.6 A4.4About 70 minutes
Learning goals
  • I can visit every element of a list with an element loop or an index loop, and choose the right one.
  • I can write an accumulator to find the total and the average of a list.
  • I can count the elements that meet a condition, using a loop with an if inside it (a nested structure).
  • I can trace a loop over a list in a trace table to predict its output.

Words to know

traverse
To visit every element of an array, usually from index 0 to the end, with a loop.
accumulator
A variable that builds up a result as a loop runs, e.g. a running total that starts at 0.
counter
An accumulator that goes up by 1 each time something happens.
nested structure
A control structure inside another one, such as an if inside a for loop.
trace table
A table with one column per variable and one row per step, used to follow a program by hand.
augmented assignment
A shortcut such as total += x, which means total = total + x.

A season of snow

A ski hill near Collingwood records how many centimetres of snow fall each day. At the end of the season the manager wants three numbers: the total snowfall, the average per day, and how many days had more than 10 cm. A list holds the data. A loop that visits every element, called traversing the list, finds the answers. These three algorithms (total, average, count) are on the curriculum's list of must-know array algorithms, and you will use them in almost every program from now on.

Remember from Programming Basics

for i in range(n): repeats n times with i = 0, 1, ..., n − 1. An if inside a loop runs on every pass. You also saw counters like count = count + 1. The new idea today is pointing the loop at a list.

Two ways to traverse

Python gives you two loop patterns for lists:

  • Element loop: for x in a: The loop variable takes each value in turn. It is short and clear. Use it when you only need to read the values.
  • Index loop: for i in range(len(a)): The loop variable takes each index 0, 1, ..., len(a) − 1, and you reach the value with a[i]. Use it when you need to change elements, compare neighbours, or report where something is.

Because range(len(a)) stops at len(a) − 1, an index loop can never go out of bounds. That is why you should loop with range(len(a)) and not with a typed-in number.

for x in a:x is each ELEMENT in turn739x = 7, then 3, then 9use it to read values(count, total, search)for i in range(len(a)):i is each INDEX in turn703192i = 0, 1, 2; a[i] = 7, 3, 9use it to change elementsor to report positions
The same three-element list traversed two ways. An element loop hands you the values; an index loop hands you the positions, and a[i] gets the value.

The accumulator pattern: totals and averages

To add up a list:

  1. Before the loop, make an accumulator total = 0.
  2. Inside the loop, add each element: total = total + x (or the shortcut total += x).
  3. After the loop, total holds the sum.

The average (mean) is the total divided by the number of elements, total / len(a).

snow = [12, 0, 5, 30, 2]
total = 0
for cm in snow:
total = total + cm
print("Total:", total)
print("Average:", total / len(snow))

Output: Total: 49 and Average: 9.8. 12 + 0 + 5 + 30 + 2 = 49, and 49 ÷ 5 = 9.8.

snow1200152303241212174749totalstart: total = 0; each step: total = total + elementafter the last step, total = 49
The accumulator total after each pass of the loop over snow. It starts at 0 and grows: 12, 12, 17, 47, 49. The last value (shaded differently) is the answer.

Counting with a condition

To count the elements that pass a test, put an if inside the loop. A structure inside another structure is called a nested structure. Only when the test is true does the counter go up.

temps = [-14, -3, -22, -8, -17, 1, -11]
cold_days = 0
for t in temps:
if t < -10:
cold_days = cold_days + 1
print(cold_days, "days colder than -10")

Output: 4 days colder than -10. The four values that are less than −10 are −14, −22, −17 and −11. (−10 itself would not count, because the test is < and not <=.)

Changing every element

Suppose a teacher adds 5 bonus marks to every mark. An element loop cannot do it: the loop variable is just a copy of the value, so changing it does not change the list. Use an index loop and assign to a[i].

marks = [62, 75, 88]
for m in marks:
m = m + 5 # changes only the loop variable
print(marks)
for i in range(len(marks)):
marks[i] = marks[i] + 5 # changes the list
print(marks)

Output: [62, 75, 88] and then [67, 80, 93]. The first loop changed only the variable m each time; the second loop changed the elements themselves.

Tracing a loop

A trace table lets you run a program on paper. Make one column for each variable and add a row every time a variable changes. Tracing is the best way to find logic errors: the program runs, but gives a wrong answer.

Worked example

Example 1: Trace table

Trace this program and predict the output.

a = [4, -2, 7, -5, 6]

pos_total = 0

neg_count = 0

for x in a:

    if x > 0:

        pos_total += x

    else:

        neg_count += 1

print(pos_total, neg_count)

  1. Make columns for x, pos_total and neg_count. Start: pos_total = 0, neg_count = 0.
  2. x = 4: positive, pos_total = 4.
  3. x = −2: not positive, neg_count = 1.
  4. x = 7: pos_total = 4 + 7 = 11.
  5. x = −5: neg_count = 2.
  6. x = 6: pos_total = 11 + 6 = 17.
  7. The loop ends and prints both accumulators. Notice that 0 would land in the else and be counted as negative, which is a logic error if the list could contain 0. A safer test is elif x < 0:.

17 2

Stepxx > 0?pos_totalneg_count
start––00
14yes40
2-2no41
37yes111
4-5no112
56yes172
The trace table for Example 1. One row per pass of the loop.
Worked example

Example 2: Above-average marks

Write a program that finds the average of marks = [78, 91, 66, 85, 70] and then counts how many marks are above the average.

  1. You need the average before you can compare, so this takes two traversals: one to total, one to count.
  2. Loop 1: total = 78 + 91 + 66 + 85 + 70 = 390. Average = 390 ÷ 5 = 78.0.
  3. Loop 2: compare each mark with 78.0. 91 and 85 are greater. 78 is equal, not above, so it does not count.
  4. Code: marks = [78, 91, 66, 85, 70] total = 0 for m in marks:     total += m average = total / len(marks) above = 0 for m in marks:     if m > average:         above += 1 print("Average:", average) print("Above average:", above)

Average: 78.0 and Above average: 2

Avoid dividing by zero

If the list could be empty, total / len(a) raises ZeroDivisionError. Check first: if len(a) > 0: before computing the average, and print a helpful message otherwise.

Just for fun

Average facts: if you put one foot in a bucket of ice water and the other in a hot bath, on average you are perfectly comfortable. This is why programmers sometimes report the count, the highest and the lowest along with the average.

Hands-on activity

Your own data, your own totals

You need: a computer with Python, and a week or more of real numbers from your life. Ideas: minutes of screen time each day (from your phone's settings), the daily high temperature from a weather app, or the price of each item on a grocery receipt.

  1. Type the numbers into a list.
  2. Write a program that prints the total, the average (rounded with round(avg, 1)), and a count of how many values pass a test you choose (e.g. days over 120 minutes, days below 0 °C, items over $5).
  3. Trace your program by hand for the first three elements in a trace table, then run it and compare.
  4. Change one value in the list and predict how each answer will change before running again.

What to look for: the accumulator starts at 0 before the loop, and the division happens after the loop.

Your turn

1

Write an element loop that prints every name in names, one per line.

2

Write code that finds the total of costs = [4.25, 1.50, 3.00] with an accumulator.

3

What is wrong with putting total = 0 inside the loop?

4

Predict the output:

a = [3, 8, 1, 9, 4]

c = 0

for x in a:

    if x >= 4:

        c += 1

print(c)

5

When must you use for i in range(len(a)) instead of for x in a?

6

Write code that doubles every element of a in place.

7

What error happens with print(sum_total / len(a)) when a is empty? How do you avoid it?

More practice: warm-up

1

What does total += 5 mean?

2

What should a counter start at?

3

How many times does for x in [5, 6, 7, 8]: repeat?

4

In for i in range(len(a)): with len(a) == 6, what is the last value of i?

5

What is the average of 4, 6 and 11?

More practice: on your own

1

Predict the output:

a = [2, 5, 8]

s = 0

for i in range(len(a)):

    s += a[i] * i

print(s)

2

Write a program that counts how many words in words = ["snow", "ice", "toque", "sled", "mitts"] have more than 4 letters.

3

This code should print the average, but prints 15.0 for [10, 20, 30]. Find the logic error.

a = [10, 20, 30]

total = 0

for x in a:

    total += x

print(total / (len(a) + 1))

4

Write code that prints the index of every negative temperature in temps.

5

Write code that finds both the total of the even numbers and the count of the odd numbers in a list a in one loop.

Challenge

1

Write code that counts how many times the temperature rose from one day to the next in temps = [-5, -3, -8, -1, 2, 2]. Why does the loop use range(len(temps) - 1)?

2

Write a program that reads marks (one per line) until the user enters −1, stores them in a list, and prints the number of marks and the average. Make sure entering −1 right away does not crash.

3

The range of a data set is highest − lowest. Without using max() or min(), explain why you cannot find the range of a list with one accumulator that starts at 0, and say what you would track instead.

Check your understanding

Quiz

1.

Where should total = 0 go when adding up a list?

2.

What does this print? a = [5, 1, 4], t = 0, for x in a: t += x, print(t / len(a))

3.

Which loop can change the elements of list a?

4.

A loop counts days with if t < -10:. Which day is not counted?

5.

What is a nested structure?

6.

For a = [8, 3, 6], which index loop visits every element without going out of bounds?

For parents and teachers

Big idea: Expectation A2.3 names these array algorithms: counting elements, calculating a total, finding the highest or lowest value, and linear search. This lesson covers counting, totals and averages. A4.4 (tracing) is practised with trace tables.

How to help: Ask your teen to trace a short loop out loud while you write the trace table, then swap roles. Real data from home (receipts, temperatures, screen time) makes the activity meaningful.

Common difficulties:

  • Starting the accumulator inside the loop, or forgetting to start it at all (NameError).
  • Trying to change elements with an element loop (for x in a: x = ...).
  • Off-by-one when comparing neighbours: use range(len(a) - 1) when the body uses a[i + 1].
  • Dividing by zero for an empty list.
  • Using < when the question means "at most" or "at least" (<=, >=). Read the wording carefully.