Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
The Standard Toolbox  ›  Lesson

itertools

Itertools 16 minLazy building blocks for combining and slicing iterables
Your task
Write menu_combinations(mains, sides): return every [main, side] pairing as a list of two-item lists, using itertools.product. Example: menu_combinations(["dosa", "idli"], ["chutney", "sambar"]) -> [["dosa", "chutney"], ["dosa", "sambar"], ["idli", "chutney"], ["idli", "sambar"]].

itertools

In short: itertools gives lazy building blocks for combining and slicing iterables without materialising an extra list first. chain(a, b) walks several iterables end to end as if they were one. product(a, b) gives every pairing of two iterables — nested loops, flattened into one call. groupby collapses runs of equal neighbours into groups; it does not group the whole sequence by key unless you sort first. islice slices an iterator the way [start:stop:step] slices a list, which matters because a generator can't be indexed at all. Reach for one of these before writing the nested loop or nested nested-if by hand.

Two belts of items merging end to end into one lazy stream labelled chain, beside a grid of every red/blue times S/M/L pairing labelled product, with a note that groupby only merges neighbouring equal items, not the whole list

Combine two menus into one listing

A breakfast menu and a lunch menu need to print as one combined list. + only works when both sides are the same concrete type — it breaks the moment one side is a generator instead of a list:

What happens when you run this?
breakfast = ["idli", "dosa"]
lunch = (item for item in ["rice", "dal"])   # a generator, not a list
print(breakfast + lunch)

chain walks any iterables end to end, lazily — it never builds the combined sequence in memory before you start reading it:

python

Every outfit combination

A shop wants every size/colour combination it stocks, to generate a page for each. Nested loops do it, but product says the same thing in one line:

python

product also takes repeat= for combining one iterable with itself — every sequence of n coin flips, say:

python

Group consecutive log levels

A log file's levels need collapsing into runs — how many INFO lines in a row, before the next ERROR. groupby does exactly that, but only for neighbours:

What does this print?
from itertools import groupby

logs = ["INFO", "INFO", "ERROR", "INFO"]
groups = [key for key, _ in groupby(logs)]
print(groups)

If you want every INFO merged into a single group regardless of where it sits, sorted() first — groupby only ever sees what's already next to each other:

python

One more: islice

A generator has no [5:10] — it isn't indexable. islice slices it anyway, without turning it into a list first (which would defeat the point of a generator that might never end):

python

Quick practice

What does this print?
from itertools import chain

a = [1, 2]
b = [3, 4]
combined = chain(a, b)
print(list(combined), list(combined))
broken — fix itTypeError

Run it and read the error. Fix the line so it actually counts the outcomes.


🎯 Your turn

Write menu_combinations(mains, sides): return every [main, side] pairing as a list of two-item lists, using itertools.product.

  • menu_combinations(["dosa", "idli"], ["chutney", "sambar"]) → [["dosa", "chutney"], ["dosa", "sambar"], ["idli", "chutney"], ["idli", "sambar"]]
  • menu_combinations([], ["chutney"]) → []

Hint: product(mains, sides) yields (main, side) tuples — turn each into a list: [list(pair) for pair in product(mains, sides)].

Press ▶ Run and hit ✓ Check. ✅

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upCombine two menus

Write combine_menus(a, b) returning every item of a followed by every item of b, as one list, using itertools.chain.

chain
DrillEvery sequence of rolls

Write all_outcomes(faces, rolls) returning every possible sequence of rolls rolls, each as a list, using itertools.product with repeat=rolls.

product
BuildGroup consecutive items

Write group_consecutive(items) returning [[key, [items...]], ...] for each run of consecutive equal items, using itertools.groupby. Do not sort — runs must stay in their original order.

groupby
BossThe first n values from a never-ending generator

Write first_multiples(n, step): using an infinite generator that yields 0, step, 2*step, ..., return the first n values as a list, using itertools.islice.

islice
CapstoneMerge sources, then compress runs

Write compress_log(sources): sources is a list of lists of log levels. Chain them all into one stream in order, then return just the keys of each consecutive run (drop the counts), using chain.from_iterable and groupby.

chaingroupby
menu_combinations.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
menu_combinations(mains, sides) → listEvery [main, side] pairing.
try:
returned
No app map for this section yet.
Press Run to execute your code.
Press Check to run the tests for this lesson.