Grouping
Group Sum
Accumulate numeric totals per category from parallel label and value lists.
Each new category is seeded at 0 the first time it is seen; subsequent visits
add to the existing total. The trace shows sums growing and updating one
step at a time.
By hand
Walk cats and vals together with zip. For each pair, seed sums[cat]
to 0 if the key has not been seen before, then add val to it.
naive.py
Replay: real traced execution (multi-file project)
cats = ['a', 'b', 'a', 'c', 'b', 'a', 'b', 'c']
vals = [3, 5, 7, 2, 8, 4, 6, 9]
sums = {}
for cat, val in zip(cats, vals):
if cat not in sums:
sums[cat] = 0
sums[cat] = sums[cat] + val
print('RESULT:', {k: sums[k] for k in sorted(sums)})
cats ← ['a', 'b', 'a', 'c', 'b', 'a', 'b', 'c']
1cats = ['a', 'b', 'a', 'c', 'b', 'a', 'b', 'c']2vals = [3, 5, 7, 2, 8, 4, 6, 9]values this step['a', 'b', 'a', 'c', 'b', 'a', 'b', 'c']catsvals ← [3, 5, 7, 2, 8, 4, 6, 9]
1cats = ['a', 'b', 'a', 'c', 'b', 'a', 'b', 'c']2vals = [3, 5, 7, 2, 8, 4, 6, 9]3sums = {}values this step[3, 5, 7, 2, 8, 4, 6, 9]valssums ← {}
2vals = [3, 5, 7, 2, 8, 4, 6, 9]3sums = {}4for cat, val in zip(cats, vals):values this step{}sumscat ← 'a', val ← 3, sums ← {'a': 3}
pass 1 of 23sums = {}4for cat, val in zip(cats, vals):5 if cat not in sums:6 sums[cat] = 07 sums[cat] = sums[cat] + val8print('RESULT:', {k: sums[k] for k in sorted(sums)})values this step'a'cat3val{'a': 0} → {'a': 3}sumscat ← 'b', val ← 5, sums ← {'a': 3, 'b': 5}
pass 2 of 23sums = {}4for cat, val in zip(cats, vals):5 if cat not in sums:6 sums[cat] = 07 sums[cat] = sums[cat] + val8print('RESULT:', {k: sums[k] for k in sorted(sums)})values this step'a' → 'b'cat3 → 5val{'a': 3, 'b': 0} → {'a': 3, 'b': 5}sumscat ← 'a', val ← 7
3sums = {}4for cat, val in zip(cats, vals):5 if cat not in sums:values this step'b' → 'a'cat5 → 7valif cat not in sums:
4for cat, val in zip(cats, vals):5 if cat not in sums:6 sums[cat] = 0sums ← {'a': 10, 'b': 5}
6 sums[cat] = 07 sums[cat] = sums[cat] + val8print('RESULT:', {k: sums[k] for k in sorted(sums)})values this step{'a': 3, 'b': 5} → {'a': 10, 'b': 5}sumscat ← 'c', val ← 2
3sums = {}4for cat, val in zip(cats, vals):5 if cat not in sums:values this step'a' → 'c'cat7 → 2valif cat not in sums:
4for cat, val in zip(cats, vals):5 if cat not in sums:6 sums[cat] = 0sums ← {'a': 10, 'b': 5, 'c': 0}
5if cat not in sums:6 sums[cat] = 07sums[cat] = sums[cat] + valvalues this step{'a': 10, 'b': 5} → {'a': 10, 'b': 5, 'c': 0}sumssums ← {'a': 10, 'b': 5, 'c': 2}, cat ← 'b', val ← 8
pass 1 of 43sums = {}4for cat, val in zip(cats, vals):5 if cat not in sums:6 sums[cat] = 07 sums[cat] = sums[cat] + val8print('RESULT:', {k: sums[k] for k in sorted(sums)})values this step{'a': 10, 'b': 5, 'c': 0} → {'a': 10, 'b': 5, 'c': 2}sums'c' → 'b'cat2 → 8valAll 4 passes — pass 1 is the card above pass sumscatval1 {'a': 10, 'b': 5, 'c': 0} → {'a': 10, 'b': 5, 'c': 2} 'c' → 'b' 2 → 8 2 {'a': 10, 'b': 5, 'c': 2} → {'a': 10, 'b': 13, 'c': 2} 'b' → 'a' 8 → 4 3 {'a': 10, 'b': 13, 'c': 2} → {'a': 14, 'b': 13, 'c': 2} 'a' → 'b' 4 → 6 4 {'a': 14, 'b': 13, 'c': 2} → {'a': 14, 'b': 19, 'c': 2} 'b' → 'c' 6 → 9 sums ← {'a': 14, 'b': 19, 'c': 11}
6 sums[cat] = 07 sums[cat] = sums[cat] + val8print('RESULT:', {k: sums[k] for k in sorted(sums)})values this step{'a': 14, 'b': 19, 'c': 2} → {'a': 14, 'b': 19, 'c': 11}sumsfor cat, val in zip(cats, vals):
3sums = {}4for cat, val in zip(cats, vals):5 if cat not in sums:stdout ← RESULT: {'a': 14, 'b': 19, 'c': 11}
7 sums[cat] = sums[cat] + val8print('RESULT:', {k: sums[k] for k in sorted(sums)})values this stepRESULT: {'a': 14, 'b': 19, 'c': 11}stdout
The Pythonic way
defaultdict(int) auto-initialises any new key to 0, eliminating the
explicit seed check. The loop body shrinks to a single += line.
library.py
from collections import defaultdict
cats = ['a', 'b', 'a', 'c', 'b', 'a', 'b', 'c']
vals = [3, 5, 7, 2, 8, 4, 6, 9]
sums = defaultdict(int)
for cat, val in zip(cats, vals):
sums[cat] += val
print('RESULT:', {k: sums[k] for k in sorted(sums)})
RESULT: {'a': 14, 'b': 19, 'c': 11}
Implementation notes
dict.get(k, 0) + vis an alternative todefaultdict: writesums[cat] = sums.get(cat, 0) + valto avoid the seed branch entirely.sumsis printed via{k: sums[k] for k in sorted(sums)}to give alphabetical key order regardless of insertion order.- The
if cat not in sumsevents are zero-delta in the trace; the key state change appears on thesums[cat] = 0orsums[cat] = sums[cat] + valline.