Data Structures and Object-Oriented Programming

Chapter 7: List Comprehensions, Map, and Filter

1. Why these tools matter

When you’re looping just to build or transform a list, plain for-loops can feel wordy:

squares = []
for x in numbers:
    squares.append(x ** 2)

Python gives us three “power shortcuts” that turn that loop into a single, readable line:

GoalShortcutThink of it as…
Build a new listList comprehensionA recipe that says “take every x and do this to it.”
Transform every itemmap()A conveyor belt that runs every piece through the same machine.
Select certain itemsfilter()A sieve that keeps only what passes a test.

2. List Comprehensions – building lists in one line

squares = [x**2 for x in numbers]
  • Template[expression for item in iterable if condition]
  • Expression: what you want each item to become ( x**2 above).
  • Condition (optional): keep only items that pass ( x % 2 == 0 ).
even_squares = [x**2 for x in numbers if x % 2 == 0]

Nested comprehensions (flattening 2-D things)

flat = [num for row in matrix for num in row]

Read it left-to-right: “for each row then for each num in that row, collect num.”

When to use

  • Simple transform or filter.
  • You still recognise the result by reading the one-liner left-to-right. If the logic feels like a tongue-twister, fall back to a normal loop.

3. map() – running every element through the same function

strings = list(map(str, numbers))  # ➜ ['1', '2', '3', '4', '5']
  • Signature: map(function, iterable)
  • Returns an iterator (lazy). Wrap in list() or loop over it to see results.
  • Great for type conversions or re-using an existing function:
areas = list(map(math.pi.__mul__, radii))   # multiply each radius by π

(The function here is “multiply by π.”)


4. filter() – keeping only what passes a test

digits = list(filter(str.isdigit, mixed))
  • Signature: filter(function, iterable)

    • function should return True for items to keep.
    • Pass None to automatically drop any “falsy” values (0, "", [], None, False).
truthy = list(filter(None, values))

Just like map(), filter() is lazy—wrap in list() to materialise it.


5. Choosing between them

SituationBest pickWhy
“Take every item and turn it into something else.”map() or list comprehensionBoth are clear; comprehension is shorter if it’s only one expression.
“Keep only items that satisfy a rule.”filter() or list comprehension with ifPick the one that reads more naturally.
“Transform and select in one pass.”List comprehensionIt lets you attach the if right after the expression.

6. Quick Practice Exercises

  1. Cubes of odd numbers

    numbers = range(10)
    # your one-liner here
  2. Upper-case all non-empty strings

    words = ["apple", "", "Banana", " ", "cherry"]
  3. Filter out prime numbers only Hint: write a helper is_prime(n) and pass it to filter().

(Try these, then scroll back to check your answers!)


7. Key take-aways

  • List comprehensions shine for readable, compact list building.
  • map() is a conveyor belt: same function, every item.
  • filter() is a sieve: select items that pass the test.
  • All three return iterators in modern Python—wrap in list() when you need the whole thing at once.
Back to Data Structures and Object-Oriented Programming