Build an inverse index from tags with defaultdict
An inverse index reverses a familiar relationship. Rather than asking which tags belong to item-17, it lets callers ask which item IDs have the sale tag. defaultdict(list) fits the construction loop because a missing tag automatically receives a fresh empty list when by_tag[tag] is read during append().
Each input row in this example is an item ID and a tuple of tag strings. The nested loop appends that ID under every tag it contains. Consequently, by_tag["sale"] becomes ['item-17', 'item-23'], preserving the input encounter order. The assertions check both that shared tags group multiple IDs and that a tag occurring once remains a one-element list.
A defaultdict changes on missing [] access: writing by_tag["archived"] would create and store an empty list. For a read-only lookup that must not alter the index, use by_tag.get("archived"), as shown. This recipe retains duplicate IDs if an input row repeats the same tag; normalize tags or use defaultdict(set) when uniqueness matters. Tags must also be hashable, and the index does not update itself if the original item-to-tags records later change.
This draft used AI assistance.
Source: Python defaultdict documentation
Example
from collections import defaultdict
items = [
("item-17", ("red", "sale")),
("item-23", ("sale", "small")),
("item-31", ("red",)),
]
by_tag = defaultdict(list)
for item_id, tags in items:
for tag in tags:
by_tag[tag].append(item_id)
assert by_tag["sale"] == ["item-17", "item-23"]
assert by_tag["small"] == ["item-23"]
assert "archived" not in by_tag
missing = by_tag.get("archived")
assert missing is None
assert "archived" not in by_tag
print(f"sale: {by_tag['sale']}")
print(f"red: {by_tag['red']}")
print(f"archived: {missing}")
Expected stdout
sale: ['item-17', 'item-23']
red: ['item-17', 'item-31']
archived: None
Comments
Post a Comment