| name | use-defaultdict-groups |
| description | For grouping and auto-initialization: adjacency lists, grouping by key, multi-maps, nested structures without KeyError handling. |
use-defaultdict-groups
When to Use
- Building adjacency lists for graphs
- Grouping items by some key
- Multi-maps (key -> list of values)
- Nested dict structures
- Avoiding
if key not in dict checks
- Counting (though Counter is often better)
When NOT to Use
- Simple key-value mapping (use regular dict)
- When missing key should raise error
- When default value is complex/expensive
The Pattern
Use defaultdict to auto-initialize missing keys.
from collections import defaultdict
groups = defaultdict(list)
groups['a'].append(1)
groups['a'].append(2)
unique_groups = defaultdict(set)
unique_groups['a'].add(1)
unique_groups['a'].add(1)
counts = defaultdict(int)
counts['a'] += 1
tree = lambda: defaultdict(tree)
d = tree()
d['a']['b']['c'] = 1
Example (from pytudes)
from collections import defaultdict
class multimap(defaultdict):
"""A mapping of {key: [val1, val2, ...]}."""
def __init__(self, pairs=(), symmetric=False):
self.default_factory = list
for key, val in pairs:
self[key].append(val)
if symmetric:
self[val].append(key)
edges = [('a', 'b'), ('a', 'c'), ('b', 'd')]
graph = multimap(edges, symmetric=True)
students = [('Alice', 'Math'), ('Bob', 'CS'), ('Carol', 'Math')]
by_major = defaultdict(list)
for name, major in students:
by_major[major].append(name)
units = defaultdict(list)
for unit in all_units:
for square in unit:
units[square].append(unit)
Key Principles
- Factory, not value: Pass
list, not []
- Auto-creates on access: Even
d[key] creates entry
- Symmetric graphs: Add both directions for undirected
- Nesting:
defaultdict(lambda: defaultdict(int))
- Check existence carefully:
key in d before access if you don't want creation