Count, total and group by key
One pass over the records can build a dictionary keyed by category: orders per channel, revenue per state, order IDs per customer.
- Choose a key and a starting value (0 for counts and totals, an empty list for groups)
- Create a key the first time it appears, then update it with
+=orappend - Read the finished dictionary with
items()to answer a question about it
Questions like *how many orders came from each channel?* need one answer per category, and you don't know the categories in advance. A dictionary fits: the key is the category, and the value is what you collect for it.
Every version of this pattern makes the same decision on each pass: is this key new? If it is, store a starting value: 0 for a count or a total, an empty list for a group. Then update the value stored under that key.
Run each example to see what it prints. Running examples doesn't count toward progress.
channels = ["web", "app", "web", "phone", "app", "web"] counts = {} for channel in channels: if channel not in counts: counts[channel] = 0 counts[channel] += 1 print(counts)
channels = ["web", "app"] counts = {} for channel in channels: counts[channel] += 1 print(counts)
The value can be a running total instead of a count: add the order's total instead of 1. Or it can be a list that you append to. A list per key is a group: every record that shares the key ends up together, in the order they were seen.
def orders_by_customer(orders): groups = {} for order in orders: customer = order["customer_id"] if customer not in groups: groups[customer] = [] groups[customer].append(order["order_id"]) return groups orders = [ {"order_id": "O100282", "customer_id": "C00077"}, {"order_id": "O100918", "customer_id": "C01338"}, {"order_id": "O101219", "customer_id": "C00077"}, {"order_id": "O101723", "customer_id": "C01338"}, {"order_id": "O101777", "customer_id": "C00305"}, ] for customer, ids in orders_by_customer(orders).items(): print(customer, len(ids), ids)
When to use it: any *per* question: per channel, per state, per product, per customer. Counts and totals use 0; groups use []. Mistake to avoid: creating the starting value on every pass instead of only the first. The concept check shows what that does.
- Pick the key (what you group by) and the starting value (0 for counts and totals,
[]for groups). - On each pass: create the key if it is new, then update it with
+=orappend. d[k] += xreads the old value first, so a missing key raises KeyError.- Next: a dictionary keyed by ID can join two collections.