Capstone. Given a list of transaction dicts with category and amount, you want one function that returns {"total_count": 3, "total_amount": 70, "by_category": {"Food": 25, "Gas": 45}, "categories": ["Food", "Gas"]}. Count, sum, group-and-aggregate, unique values. Every pattern you've built this month. How do you compose them?
Total count is len(items). Total amount is a sum() generator expression. The per-category dict is the Day 25 aggregate. Unique categories is a sorted set comprehension. Four operations.
Exactly — each one is a pattern you've already solved. The capstone is just wiring them into a single return dict. Guard first for empty input so the reduce operations don't surprise you:
if not items:
return {"total_count": 0, "total_amount": 0, "by_category": {}, "categories": []}Then compute each field and compose into one return.
And the per-category sum is the aggregate pattern from Day 25 — totals.get(key, 0) + amount?
Exactly that pattern, inlined. The whole function is composition:
def analyze_data(items: list) -> dict:
if not items:
return {"total_count": 0, "total_amount": 0, "by_category": {}, "categories": []}
by_cat = {}
for it in items:
c = it["category"]
by_cat[c] = by_cat.get(c, 0) + it["amount"]
return {
"total_count": len(items),
"total_amount": sum(it["amount"] for it in items),
"by_category": by_cat,
"categories": sorted({it["category"] for it in items})
}Four patterns composed: len, sum, accumulator, set-sorted.
The generator expression in sum() — sum(it["amount"] for it in items) without square brackets?
Right — when an expression is the sole argument of a function call, you can drop the [] around the comprehension. Python treats it as a generator, which is more memory-efficient for large inputs. Same result as sum([it["amount"] for it in items]), but no intermediate list is built.
So the whole track collapses into this one function. Every pattern, one file, real analysis.
That's the payoff. A pipeline you can read top to bottom — guard, accumulate, compose, return. Change the input shape and you've built a report generator for any dataset. This is what 30 days of practice converts into: the ability to sketch and ship a real analysis function without looking anything up.
TL;DR: Guard empty input → accumulate per category → compose a return dict from four reductions.
min/max on empty, etc.sum(x for x in items) — generator expression, memory-efficient| Week | Pattern used |
|---|---|
| 1 | set comprehension for unique categories |
| 2 | sum for total amount (reduction) |
| 3 | dict spread could merge optional fields |
| 4 | group-by accumulator for by_category |
Four weeks of patterns land in one function.
Capstone. Given a list of transaction dicts with category and amount, you want one function that returns {"total_count": 3, "total_amount": 70, "by_category": {"Food": 25, "Gas": 45}, "categories": ["Food", "Gas"]}. Count, sum, group-and-aggregate, unique values. Every pattern you've built this month. How do you compose them?
Total count is len(items). Total amount is a sum() generator expression. The per-category dict is the Day 25 aggregate. Unique categories is a sorted set comprehension. Four operations.
Exactly — each one is a pattern you've already solved. The capstone is just wiring them into a single return dict. Guard first for empty input so the reduce operations don't surprise you:
if not items:
return {"total_count": 0, "total_amount": 0, "by_category": {}, "categories": []}Then compute each field and compose into one return.
And the per-category sum is the aggregate pattern from Day 25 — totals.get(key, 0) + amount?
Exactly that pattern, inlined. The whole function is composition:
def analyze_data(items: list) -> dict:
if not items:
return {"total_count": 0, "total_amount": 0, "by_category": {}, "categories": []}
by_cat = {}
for it in items:
c = it["category"]
by_cat[c] = by_cat.get(c, 0) + it["amount"]
return {
"total_count": len(items),
"total_amount": sum(it["amount"] for it in items),
"by_category": by_cat,
"categories": sorted({it["category"] for it in items})
}Four patterns composed: len, sum, accumulator, set-sorted.
The generator expression in sum() — sum(it["amount"] for it in items) without square brackets?
Right — when an expression is the sole argument of a function call, you can drop the [] around the comprehension. Python treats it as a generator, which is more memory-efficient for large inputs. Same result as sum([it["amount"] for it in items]), but no intermediate list is built.
So the whole track collapses into this one function. Every pattern, one file, real analysis.
That's the payoff. A pipeline you can read top to bottom — guard, accumulate, compose, return. Change the input shape and you've built a report generator for any dataset. This is what 30 days of practice converts into: the ability to sketch and ship a real analysis function without looking anything up.
TL;DR: Guard empty input → accumulate per category → compose a return dict from four reductions.
min/max on empty, etc.sum(x for x in items) — generator expression, memory-efficient| Week | Pattern used |
|---|---|
| 1 | set comprehension for unique categories |
| 2 | sum for total amount (reduction) |
| 3 | dict spread could merge optional fields |
| 4 | group-by accumulator for by_category |
Four weeks of patterns land in one function.
Write `analyze_data(items)` that takes a list of dicts (each with `"category"` and `"amount"`) and returns a dict with keys `total_count` (int), `total_amount` (number), `by_category` (dict of totals per category), and `categories` (sorted list of unique categories). Return zero-defaults for an empty list.
Tap each step for scaffolded hints.
No blank-editor panic.