You have a list of book dicts with category and title fields. You want them sorted by category first, then by title within each category. How do you tell sorted() to use two fields?
Return both values from the lambda? Like a tuple?
Exactly. A lambda can return a tuple, and Python compares tuples element by element — it uses the first element first, and only falls back to the second if the first is equal. That's how multi-field sort works:
sorted(books, key=lambda b: (b["category"], b["title"]))Category first, title as tiebreaker. Two books with the same category sort alphabetically by title.
So the tuple ("Fiction", "A Tale") versus ("Fiction", "Zebra") compares by the first element, sees both are "Fiction", then compares the second?
That's the tuple ordering protocol. ("Fiction", "A Tale") < ("Fiction", "Zebra") is True because the categories tie and "A Tale" < "Zebra" alphabetically. No special syntax required:
def multi_field_sort(books: list) -> list:
return sorted(books, key=lambda b: (b["category"], b["title"]))One lambda, two fields, correct ordering at every level.
What if I want the secondary field descending while the primary stays ascending — like newest first within each category?
For numeric fields, negate them: (b["category"], -b["year"]). For strings, it's trickier — you'd need reverse=True on the whole sort or a different approach. But for simple ascending-on-both cases, the tuple key is a one-liner.
And this scales to three or four fields the same way? Just add more tuple elements?
Exactly. (a, b, c, d) compares left to right, falling back element by element. The mental model stays the same no matter how many fields you stack. This is also why Python's stable sort matters — ties at every level preserve input order, so you can pre-sort by lower-priority fields and layer higher-priority sorts on top.
TL;DR: key=lambda x: (primary, secondary) sorts by primary first, secondary as tiebreaker.
| Tuple A | Tuple B | Order |
|---|---|---|
(1, 2) | (1, 3) | A < B (ties on 1, 2 < 3) |
(1, 5) | (2, 0) | A < B (1 < 2, second ignored) |
(3, 0) | (3, 0) | equal — stable sort preserves input order |
Python's tuple ordering is lexicographic — first-field priority, with falls to later fields.
You have a list of book dicts with category and title fields. You want them sorted by category first, then by title within each category. How do you tell sorted() to use two fields?
Return both values from the lambda? Like a tuple?
Exactly. A lambda can return a tuple, and Python compares tuples element by element — it uses the first element first, and only falls back to the second if the first is equal. That's how multi-field sort works:
sorted(books, key=lambda b: (b["category"], b["title"]))Category first, title as tiebreaker. Two books with the same category sort alphabetically by title.
So the tuple ("Fiction", "A Tale") versus ("Fiction", "Zebra") compares by the first element, sees both are "Fiction", then compares the second?
That's the tuple ordering protocol. ("Fiction", "A Tale") < ("Fiction", "Zebra") is True because the categories tie and "A Tale" < "Zebra" alphabetically. No special syntax required:
def multi_field_sort(books: list) -> list:
return sorted(books, key=lambda b: (b["category"], b["title"]))One lambda, two fields, correct ordering at every level.
What if I want the secondary field descending while the primary stays ascending — like newest first within each category?
For numeric fields, negate them: (b["category"], -b["year"]). For strings, it's trickier — you'd need reverse=True on the whole sort or a different approach. But for simple ascending-on-both cases, the tuple key is a one-liner.
And this scales to three or four fields the same way? Just add more tuple elements?
Exactly. (a, b, c, d) compares left to right, falling back element by element. The mental model stays the same no matter how many fields you stack. This is also why Python's stable sort matters — ties at every level preserve input order, so you can pre-sort by lower-priority fields and layer higher-priority sorts on top.
TL;DR: key=lambda x: (primary, secondary) sorts by primary first, secondary as tiebreaker.
| Tuple A | Tuple B | Order |
|---|---|---|
(1, 2) | (1, 3) | A < B (ties on 1, 2 < 3) |
(1, 5) | (2, 0) | A < B (1 < 2, second ignored) |
(3, 0) | (3, 0) | equal — stable sort preserves input order |
Python's tuple ordering is lexicographic — first-field priority, with falls to later fields.
Write `multi_field_sort(books)` that returns books sorted by `category` (ascending), then by `title` (ascending) within each category. Use a tuple key.
Tap each step for scaffolded hints.
No blank-editor panic.