Exercises — Dictionary and set comprehensions
Before you start, here is the one mental picture we keep reusing — the anatomy of a comprehension. Each coloured zone is a job: what you store, where the source comes in, and what you keep.

Level 1 — Recognition
Goal: read a comprehension and predict its exact output. No writing yet — just seeing.
L1.1
What is the type and value of each?
A = {}
B = {1, 2, 3}
C = {"a": 1}
D = {x for x in range(3)}Recall Solution
A→ emptydict(braces alone = dict, the classic trap).type(A)isdict.B→ aset{1, 2, 3}(values, no colon).C→ adict{"a": 1}(colon present ⇒ key:value).D→ a set comprehension producing{0, 1, 2}.
Rule used: colon anywhere in the braces ⇒ dict; otherwise a set; empty braces ⇒ dict.
L1.2
Predict the output:
{n: n + 10 for n in range(3)}Recall Solution
The DRIVE gives n = 0, 1, 2. The HEAD stores n: n+10.
Result: {0: 10, 1: 11, 2: 12}.
L1.3
Predict the output:
{len(s) for s in ["hi", "yo", "sun"]}Recall Solution
Lengths are 2, 2, 3. No colon ⇒ set, and a set drops duplicates.
The two 2s collapse to one. Result: {2, 3}.
Level 2 — Application
Goal: write a comprehension from scratch for a stated task.
L2.1
Build a dict mapping each number 1..5 to its cube.
Recall Solution
{n: n**3 for n in range(1, 6)}
# {1: 1, 2: 8, 3: 27, 4: 64, 5: 125}HEAD n: n**3, DRIVE for n in range(1, 6). range(1, 6) stops before 6, so it is 1..5.
L2.2
From nums = [4, 7, 10, 13], build a set of only the numbers divisible by 2.
Recall Solution
nums = [4, 7, 10, 13]
{x for x in nums if x % 2 == 0}
# {10, 4}The GATE if x % 2 == 0 runs before the element is kept. Only 4 and 10 pass.
(x % 2 is the remainder after dividing by 2; == 0 means "evenly divisible".)
L2.3
Build a dict mapping each word in ["cat", "dog", "ox"] to its length.
Recall Solution
words = ["cat", "dog", "ox"]
{w: len(w) for w in words}
# {'cat': 3, 'dog': 3, 'ox': 2}Note: values may repeat freely (two 3s here). Only keys must be unique — and the words
already are.
Level 3 — Analysis
Goal: reason about collisions, ordering, and what silently disappears.
L3.1
How many entries does this dict have, and which survive?
{x % 3: x for x in range(7)}Recall Solution
x runs 0..6. The key is x % 3, so keys cycle 0,1,2,0,1,2,0. Same key ⇒ later value
overwrites earlier. Track each key's last writer:
- key
0: written byx=0,3,6→ last is 6 - key
1: written byx=1,4→ last is 4 - key
2: written byx=2,5→ last is 5
Result: {0: 6, 1: 4, 2: 5} — 3 entries, not 7.
L3.2
What is the size of this set?
{abs(x) for x in [-2, -1, 0, 1, 2]}Recall Solution
abs gives 2, 1, 0, 1, 2. Distinct values: {0, 1, 2} → size 3.
Both -1,1 collapse to 1 and both -2,2 collapse to 2. That halving is the whole point of a
set: it guarantees no duplicates.
L3.3
Invert d = {"a": 1, "b": 2, "c": 1} with {v: k for k, v in d.items()}. How many entries result?
Recall Solution
.items() yields ("a",1), ("b",2), ("c",1). New keys are the old values 1, 2, 1.
Key 1 appears twice (from "a" then "c"); the later wins → "c".
Result: {1: "c", 2: "b"} → 2 entries (one grade collided).
Level 4 — Synthesis
Goal: combine comprehensions with ternaries, nesting, and other iterables.
L4.1
Map each n in 0..5 to the string "even" or "odd".
Recall Solution
{n: ("even" if n % 2 == 0 else "odd") for n in range(6)}
# {0:'even',1:'odd',2:'even',3:'odd',4:'even',5:'odd'}The Ternary conditional expression A if cond else B lives in the value slot (head). It
chooses, so every n still gets an entry — nothing is filtered out.
L4.2
From two lists names = ["Asha", "Ravi"] and scores = [90, 75], build the pairing dict.
Recall Solution
names = ["Asha", "Ravi"]
scores = [90, 75]
{name: score for name, score in zip(names, scores)}
# {'Asha': 90, 'Ravi': 75}zip walks both lists in lockstep, handing out ("Asha", 90) then ("Ravi", 75). We unpack each
pair into name, score.
L4.3
Build a set of all distinct letters appearing across ["bee", "add", "cab"].
Recall Solution
words = ["bee", "add", "cab"]
{ch for w in words for ch in w}
# {'b', 'e', 'a', 'd', 'c'}Nested drive: read the two fors left to right, outer to inner — "for each word w, for
each character ch in that word." Letters b,e,e,a,d,d,c,a,b collapse to the 5 distinct
{a, b, c, d, e}.
Level 5 — Mastery
Goal: design a small tool, choosing dict vs set and handling collisions deliberately.
L5.1
Given data = [3, 1, 4, 1, 5, 9, 2, 6, 5], build a dict mapping each distinct value to the
count of how many times it appears. (Hint: build the distinct set first, then count.)
Recall Solution
data = [3, 1, 4, 1, 5, 9, 2, 6, 5]
{v: data.count(v) for v in set(data)}
# {1: 2, 2: 1, 3: 1, 4: 1, 5: 2, 6: 1, 9: 1}Why set(data) in the DRIVE? It gives each value once, so no wasted recomputation and no
collisions. data.count(v) scans the list counting v. 1 and 5 appear twice; everything else
once. Total distinct keys = 7.
L5.2
From pairs = [("a", 1), ("b", 2), ("a", 3)], build a dict where each key keeps ALL its values
in a list (so the collision on "a" is preserved, not overwritten).
Recall Solution
A single comprehension would let "a": 3 overwrite "a": 1. To keep all, group inside the
value using the distinct keys as the drive:
pairs = [("a", 1), ("b", 2), ("a", 3)]
keys = {k for k, _ in pairs} # {'a', 'b'}
{k: [v for kk, v in pairs if kk == k] for k in keys}
# {'a': [1, 3], 'b': [2]}The outer dict comprehension drives over distinct keys; the inner list comprehension
gathers every v whose original key matched. "a" now safely holds [1, 3].
L5.3
Build a dict mapping each n in 1..10 to "fizz" if divisible by 3, "buzz" if divisible by 5,
"fizzbuzz" if by both, else n itself.
Recall Solution
{n: ("fizzbuzz" if n % 15 == 0
else "fizz" if n % 3 == 0
else "buzz" if n % 5 == 0
else n)
for n in range(1, 11)}
# {1:1, 2:2, 3:'fizz', 4:4, 5:'buzz', 6:'fizz',
# 7:7, 8:8, 9:'fizz', 10:'buzz'}Order matters: test n % 15 (both) first, otherwise a fizzbuzz number would be caught by
the n % 3 branch and mislabelled. This is a chained ternary living entirely in the value slot
— still no filtering, every n gets an entry.
Connections
- Dictionary and set comprehensions — parent topic these exercises drill
- List comprehensions — the inner
[v for ...]used in L5.2 - Ternary conditional expression — the value-chooser in L4.1 and L5.3
- Dictionaries in Python · Sets in Python — the structures being built
- Hashing and hashable types — why keys must be unique & hashable
- Generator expressions — lazy cousin using
(...)