Iterating over a list
Loops over items and indexes, totals, counts, min and max, and linear search.
Do this lesson in the simulatorA list is only useful if you can work through it. This lesson puts together two things you already know, lists and loops, into the most common thing programs do with data: go through every item and do something with it.
for over the items
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
legs = [20, 15, 30, 15]
for length in legs:
print("driving", length, "cm")
forward(60, distance=length)
turn_right(30, angle=90)
print("finished at", position())
for length in legs visits each item in turn, first to last, putting it in length. No range and no index needed when you only want the items. Change the list and the drive changes: the program is now driven by data.
for over the indexes
When you need the position as well as the item, loop over range(len(...)):
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
colours = ["red", "orange", "green"]
for i in range(len(colours)):
print("step", i, "is", colours[i])
led(colours[i])
wait(0.5)
for i, colour in enumerate(colours):
print(i, colour)
range(len(colours)) gives 0, 1, 2: every valid index. enumerate gives the index and the item together, which is often tidier.
The patterns, over a list
The loop patterns from lesson F2.7 work on any list. Python also has built-in functions for the common ones:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
readings = [41.0, 35.5, 30.2, 25.8, 20.1]
total = 0
for r in readings:
total = total + r
print("total", total, "or with sum:", sum(readings))
print("average", total / len(readings))
close = 0
for r in readings:
if r < 30:
close = close + 1
print(close, "readings under 30 cm")
print("smallest", min(readings), "largest", max(readings))
It is worth being able to write the loop yourself as well as use sum, min and max: exam questions often ask for the algorithm, and a loop can do things the built-ins cannot, such as count only the readings under 30.
Readings from the robot
Collect first, then work through the list:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
readings = []
for step in range(6):
readings.append(distance())
forward(50, distance=6)
print("readings:", readings)
biggest_drop = 0
for i in range(1, len(readings)):
drop = readings[i - 1] - readings[i]
if drop > biggest_drop:
biggest_drop = drop
print("biggest change between two readings:", round(biggest_drop, 1), "cm")
The second loop starts at index 1 so that readings[i - 1] always exists. Comparing each item with the one before it is another pattern you will use often.
Searching a list
Linear search looks at each item in turn until it finds the one it wants:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
names = ["Ada", "Alan", "Grace", "Tim"]
target = input("Who are you looking for? ")
found = False
for i in range(len(names)):
if names[i] == target:
print(target, "is at index", i)
found = True
break
if not found:
print(target, "is not in the list")
The found flag remembers whether the loop succeeded, and break stops looking once it has. Module F5 compares this with faster ways to search.
Task: sensor log
Drive forward in five steps of 8 cm, recording distance() before each step in a list. Then print four lines: readings: <the list>, smallest: <cm>, largest: <cm> and average: <cm>. Work the average out with a loop or with sum and len, not by typing numbers.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
readings = []
Challenges
- Find the smallest reading with a loop, without using
min. - Drive a shape from a list of
[distance, turn]pairs, such as[[30, 90], [20, 90], [30, 90], [20, 90]]. - Count how many names in a list start with the letter
A.