Iterating & Transforming
Intermediate · 20 min read · ▶ live playground · ✦ checkpoint
A list of scores is not useful because it sits there. It becomes useful when you can walk through it, pair it with names, reshape it, and ask quick questions like "who passed?" or "what was the best score?"
Loop over the item, not the index
When you already have a collection, the cleanest loop usually names the item you want. A collection loop is a for loop that steps through a collection one item at a time. A transformation is turning each item into a new value.
players = ["Mina", "Ravi", "Noor"]
cheers = []
for player in players:
cheers.append(player.upper() + "!")
for cheer in cheers:
print(cheer)MINA!RAVI!NOOR!
Read for player in players as "for each player in the list." Python moves the loop variable player from item to item, so you do not need to manage 0, 1, and 2 by hand.
This keeps the code focused on the job. The first loop transforms each name into a cheer and stores the results. The second loop prints the finished collection.
An accumulator list is a list you build up over time, often with append(). You used running totals in loops before; this is the collection version of that same habit.
Use enumerate when you need positions
Sometimes you do need the position. A leaderboard needs rank numbers. An edit screen might need line numbers. enumerate() is a built-in function that gives each item with its index as you loop.
players = ["Mina", "Ravi", "Noor"]
scores = [42, 35, 39]
for rank, player in enumerate(players, start=1):
print(f"{rank}. {player}")
print("Scores")
for player, score in zip(players, scores):
print(f"{player}: {score}")1. Mina2. Ravi3. NoorScoresMina: 42Ravi: 35Noor: 39
enumerate(players, start=1) gives pairs: rank, then player. Without start=1, the first index would be 0, which is perfect for positions but not for human-facing ranks.
zip() is a built-in function that pairs items from collections by position. Picture two lists like two rows of cards; zip() clips the first cards together, then the second cards, then the third. If one collection is shorter, zip() stops when the shortest one runs out.
The loop line for player, score in zip(players, scores) uses unpacking from lesson 5.2. Each pair arrives as two values, and Python assigns them to two names.
Try it - rank a tiny scoreboard
Change the scores and add a fourth player with a fourth score. Then remove one score and notice where zip() stops.
List comprehensions build new lists
A list comprehension is a compact expression that builds a new list by looping over another collection. It is not magic. It is a loop shaped into one line.
scores = [18, 10, 22, 14]
boosted_scores = []
for score in scores:
boosted_scores.append(score + 2)
passing_scores = [score for score in boosted_scores if score >= 16]
score_labels = [f"{score} pts" for score in passing_scores]
print(boosted_scores)
print(passing_scores)
print(score_labels)[20, 12, 24, 16][20, 24, 16]['20 pts', '24 pts', '16 pts']
The first loop and append() build boosted_scores in the long form. A filter is a condition that decides which items are kept. The next line builds passing_scores with a comprehension:
scorebeforeforis the value to put in the new list.for score in boosted_scoresis the loop.if score >= 16is the filter.
Use the long loop when the work takes several steps. Use a comprehension when the idea is short enough to read in one breath.
Nested comprehensions handle rows
A nested comprehension is a comprehension with one loop inside another loop. Use it for small row-shaped data, like the nested lists from lesson 5.1.
seating = [
["Ari", "Mina"],
["Ravi", "Noor"],
]
all_players = [player for row in seating for player in row]
name_lengths = [[len(player) for player in row] for row in seating]
print(all_players)
print(name_lengths)['Ari', 'Mina', 'Ravi', 'Noor'][[3, 4], [4, 4]]
all_players turns the rows into one list. Read it left to right after the first expression: for each row in seating, for each player in that row, keep player.
name_lengths keeps the row shape. The inner comprehension turns one row of names into one row of lengths. The outer comprehension repeats that for each row.
Nested comprehensions get hard to read fast. If your eyes have to backtrack twice, use normal nested loops. Clear code wins.
Built-ins answer common questions
Python gives you power built-ins for collections. A built-in is a tool Python gives you without an import.
scores = [18, 10, 22, 14]
ready = [True, True, False]
late = [False, False, True]
print(sorted(scores))
print(scores)
print(min(scores))
print(max(scores))
print(sum(scores))
print(any(late))
print(all(ready))
for score in reversed(scores):
print(f"reverse: {score}")[10, 14, 18, 22][18, 10, 22, 14]102264TrueFalsereverse: 14reverse: 22reverse: 10reverse: 18
sorted(scores) returns a new sorted list. The original scores list stays unchanged, unlike scores.sort() from lesson 5.1.
min() finds the smallest value. max() finds the largest. sum() adds numeric values.
any(late) asks, "Is at least one item truthy?" all(ready) asks, "Are all items truthy?" You already know truthiness from Section 4: True counts as yes, False counts as no.
reversed(scores) lets a loop walk through the collection from the end back to the start. It does not change the original list.
Checkpoint
Answer all three to mark this lesson complete
You now have the everyday tools for moving through collections and shaping new ones. Next, dictionaries give you collections that find values by labels instead of positions.