Unpacking Tuples in For Loops
Sorting dictionaries by value requires reconstructing tuples from (key, value) to (value, key) because Python's tuple sort compares the first element first.
Try it: Sorting with key= and reverse=
How sorted() and list.sort() compute key(item) once per item, order the items by those keys with Python's comparison rules, and keep equal keys in their original order — including py4e's sort-a-dict-by-value pattern.
How it works
- Decorate: call the key function once on every item (no key means the item itself is compared).
- Compare keys with Python's rules: ints by value, strs by code point ('Z' < 'a'), tuples item by item.
- Order the items by key; reverse=True puts the largest key first.
- Stable: items with equal keys keep their original relative order, also with reverse=True.
- sorted() returns a new list; list.sort() rearranges the list in place and returns None; [:N] keeps the first N.
Default run (12 steps): 5 items in their original order. Python will call lambda t: t[1] once per item. … sorted() returned a new list: result = [('fig', 5), ('kiwi', 5), ('pear', 3), ('apple', 3), ('date', 1)].
Simplified: Up to 10 items of one kind (ints, short ASCII words, (word, count) tuples or a small dict) and a fixed menu of key functions. The sorting algorithm itself (Timsort) is not shown — only what it guarantees: the order by key and stability.
Loading the simulation…
Try it: Tuples: Comparison and Unpacking
How Python compares tuples lexicographically — the first unequal pair of items decides, a shorter prefix is smaller, int vs str ordering raises TypeError — and how tuple assignment unpacks and swaps values.
How it works
- Walk both tuples from index 0 while the items are equal.
- At the first difference, that pair alone decides (later items are never looked at); strs compare by code point.
- If one tuple runs out first, the shorter one is smaller; ordering an int against a str raises TypeError.
- Unpacking checks the count first: too many or too few values raise ValueError before any name is bound.
- a, b = b, a builds the right-hand tuple from the old values, then unpacks it into the names.
Default run (4 steps): Evaluate (1, 'pear', 7) < (1, 'plum', 2): compare item by item from index 0. … 'pear' < 'plum' is True (strings compare by code point: 'e' is 101, 'l' is 108), so (1, 'pear', 7) < (1, 'plum', 2) is True.
Simplified: Flat tuples of up to 6 ints or short ASCII strs (no nested tuples, floats or starred targets).
Loading the simulation…
The Sorting Problem
A dictionary item is represented as a tuple in the order (key, value). If you want to sort dictionary data by value, that order is not convenient: tuple sorting examines the first element first. The solution is to unpack each item, then rebuild it as (value, key) before calling sorted().
Tuple Position and Sort Priority
Python's tuple comparison is lexicographic: it gives priority to the first element. Therefore, a tuple shaped like (key, value) is naturally ordered by key, while a tuple shaped like (value, key) is naturally ordered by value. Reconstructing the tuple changes the sort priority without changing the information it contains.
| Tuple shape | First element | Primary sorting basis |
|---|---|---|
| (key, value) | key | key |
| (value, key) | value | value |
The first tuple position determines the primary comparison.
Rebuilding Items in a Loop
The for loop receives each dictionary item as a two-part tuple. Unpacking gives the two parts names such as key and value. The loop then appends a new tuple with those names reversed: (value, key). After every item has been processed, the list contains tuples whose first elements are the values that should control sorting.
scores = {"Ada": 91, "Bo": 75, "Cy": 84}
value_key_pairs = []
for key, value in scores.items():
value_key_pairs.append((value, key))
ordered_pairs = sorted(value_key_pairs)- 1
value_key_pairsstarts as an empty list. - 2For each dictionary item, key and value receive the two tuple elements.
- 3The expression (value, key) reverses their positions before appending.
- 4
sorted()orders the completed list using the first element of each tuple.
- The dictionary supplies items in (key, value) form.
- The loop unpacks each item into key and value.
- The new tuple places value first.
sorted()can now use value as the primary comparison.
From Reconstruction to Result
Sorting three scores by value
Transform the dictionary items into (value, key) tuples and determine the result of sorted().
- 1Original items
The generated dictionary contains items represented as (key, value): (Ada, 91), (Bo, 75), and (Cy, 84).
- 2Reconstruct each tuple
Unpacking and reversing the positions produces (91, Ada), (75, Bo), and (84, Cy).
- 3Compare position 0
The first elements are 91, 75, and 84. Because value is now first, these numbers determine the primary order.
- 4Apply sorted()
The tuples are ordered from the smallest first element to the largest first element.
[(75, "Bo"), (84, "Cy"), (91, "Ada")]
Ties and Secondary Comparison
The first element remains the primary comparison. If two tuples have the same first element, lexicographic comparison can continue to the next element. For reconstructed tuples, that next element is the key. Thus, when values tie, the keys provide the next comparison position.
What do you think happens?
What order results from sorting [(8, "Zed"), (5, "Mia"), (8, "Ana")]?
Reveal answer
[(5, "Mia"), (8, "Ana"), (8, "Zed")]
The value is compared first, so 5 comes before 8. The two tuples beginning with 8 tie on their first element, so their second elements are compared next: Ana comes before Zed.
Mistakes in Value Sorting
Common mistake Sorting the original (key, value) tuples
What it looks likesorted(scores.items())Why it failsThe key is still in position 0, so tuple sorting uses the key as its primary comparison.
Do this insteadBuild a list of (value, key) tuples first, then pass that reconstructed list to sorted().
Common mistake Unpacking the item but appending the original order
What it looks likefor key, value in scores.items(): pairs.append((key, value))Why it failsThe loop names the two parts correctly, but the appended tuple leaves the key first.
Do this insteadAppend (value, key), placing the desired sorting field at position 0.
Common mistake Expecting .items() alone to provide value-sorted results
What it looks likeitems = scores.items() ordered = sorted(items)Why it failsThe .items() method gives key-value tuples, and sorting those tuples prioritizes the key.
Do this insteadManually swap the tuple positions before calling sorted().
Practice the Transformation
Given the dictionary data = {"x": 12, "y": 4, "z": 9}, write the list of reconstructed (value, key) tuples before sorting. Then predict the result of sorted() on that list.
Hints
- Each dictionary item begins in (key, value) order.
- Reverse each pair so the value comes first.
- Compare the first elements from smallest to largest.
Practice solution
Transform {"x": 12, "y": 4, "z": 9} into value-key tuples and sort them.
- 1Unpack the items
The items are (x, 12), (y, 4), and (z, 9).
- 2Reverse each tuple
The reconstructed list is [(12, x), (4, y), (9, z)].
- 3Sort by the first element
The first elements are 12, 4, and 9, so the ascending order is 4, 9, 12.
[(4, "y"), (9, "z"), (12, "x")]
The Working Pattern
- 1Dictionary items are handled as (key, value) tuples.
- 2Tuple sorting compares the first element first.
- 3To sort dictionary data by value, unpack each item and append a (value, key) tuple.
- 4Calling
sorted()on the reconstructed list produces value-based ordering. - 5If values tie, tuple comparison can continue to the key in the next position.
Key Takeaways
- Reconstruct dictionary items from (key, value) to (value, key) when value should control sorting.
- Use tuple unpacking in a for loop to access the key and value separately.
- Place the desired primary sorting field at tuple index 0.
- Apply
sorted()after building the reconstructed list. - For equal first elements, lexicographic comparison can use the next tuple element.