Day 4 routed one item at a time — branch in the loop. Today: split the list first, then act on each subset.
values = [1, 2, 11, 12, 21]
bigs = [v for v in values if v >= 10]
smalls = [v for v in values if v < 10]
print(f"bigs={bigs} smalls={smalls}")
# bigs=[11, 12, 21] smalls=[1, 2]Two list comprehensions, two subsets, no item lost.
# now act on each
for v in bigs:
side_effect_a(v)
for v in smalls:
side_effect_b(v)Why split first instead of branching in the loop?
Three reasons. First: you can print(f"bigs={len(bigs)} smalls={len(smalls)}") before any side effect. Pre-flight visibility — "about to send 3 alerts and 2 confirmations" beats "sent something". Second: if you only need to act on one subset, you don't loop the whole list. Third: it composes — yesterday you aggregated; partition is the inverse. Together: split, count, act.
Same data twice — isn't that wasteful?
Two passes over a small list cost nothing. For huge lists, you'd partition in one pass with a single for loop and two empty lists you .append to. Both shapes are valid; the comprehension version reads better at small N.
bigs = [v for v in values if v >= 10]
smalls = [v for v in values if v < 10]Two passes, two clear list expressions. Reads top-to-bottom. Good for ≤ ~1000 items.
bigs, smalls = [], []
for v in values:
(bigs if v >= 10 else smalls).append(v)One pass, slightly denser. Use when N is large enough that two passes cost real time, or when the predicate is expensive to evaluate twice.
The point of partitioning is visibility before side effects. After the split:
print(f"about to alert {len(bigs)} items, log {len(smalls)} items")
# pause here in dev — does that count look right?
for v in bigs:
alert(v)
for v in smalls:
log(v)If the pre-flight number is wrong ("about to alert 1,000 items"), you catch it before doing the wrong thing 1,000 times.
highs = [v for v in values if v > 100]
mids = [v for v in values if 10 <= v <= 100]
lows = [v for v in values if v < 10]Three comprehensions; same shape. Past 4 categories, switch to:
from collections import defaultdict
buckets = defaultdict(list)
for v in values:
buckets[categorize(v)].append(v)partition vs filterfilter keeps one subset, drops the rest.partition keeps both subsets.A partition is two filters with complementary predicates. A filter is half a partition. Pick the one that matches what you'll do downstream.
Day 4 routed one item at a time — branch in the loop. Today: split the list first, then act on each subset.
values = [1, 2, 11, 12, 21]
bigs = [v for v in values if v >= 10]
smalls = [v for v in values if v < 10]
print(f"bigs={bigs} smalls={smalls}")
# bigs=[11, 12, 21] smalls=[1, 2]Two list comprehensions, two subsets, no item lost.
# now act on each
for v in bigs:
side_effect_a(v)
for v in smalls:
side_effect_b(v)Why split first instead of branching in the loop?
Three reasons. First: you can print(f"bigs={len(bigs)} smalls={len(smalls)}") before any side effect. Pre-flight visibility — "about to send 3 alerts and 2 confirmations" beats "sent something". Second: if you only need to act on one subset, you don't loop the whole list. Third: it composes — yesterday you aggregated; partition is the inverse. Together: split, count, act.
Same data twice — isn't that wasteful?
Two passes over a small list cost nothing. For huge lists, you'd partition in one pass with a single for loop and two empty lists you .append to. Both shapes are valid; the comprehension version reads better at small N.
bigs = [v for v in values if v >= 10]
smalls = [v for v in values if v < 10]Two passes, two clear list expressions. Reads top-to-bottom. Good for ≤ ~1000 items.
bigs, smalls = [], []
for v in values:
(bigs if v >= 10 else smalls).append(v)One pass, slightly denser. Use when N is large enough that two passes cost real time, or when the predicate is expensive to evaluate twice.
The point of partitioning is visibility before side effects. After the split:
print(f"about to alert {len(bigs)} items, log {len(smalls)} items")
# pause here in dev — does that count look right?
for v in bigs:
alert(v)
for v in smalls:
log(v)If the pre-flight number is wrong ("about to alert 1,000 items"), you catch it before doing the wrong thing 1,000 times.
highs = [v for v in values if v > 100]
mids = [v for v in values if 10 <= v <= 100]
lows = [v for v in values if v < 10]Three comprehensions; same shape. Past 4 categories, switch to:
from collections import defaultdict
buckets = defaultdict(list)
for v in values:
buckets[categorize(v)].append(v)partition vs filterfilter keeps one subset, drops the rest.partition keeps both subsets.A partition is two filters with complementary predicates. A filter is half a partition. Pick the one that matches what you'll do downstream.
Create a free account to get started. Paid plans unlock all tracks.