Nested List Comprehensions
Lambda functions used as sort keys provide a temporary comparison value for each element without modifying the original list.
From Nested Input to Flat Output
A list comprehension creates a new list by taking elements from a source list, transforming them, and optionally filtering them. A nested list comprehension applies that same idea while moving through more than one level of input. The important question is not only what expression is calculated, but also which loop runs first and how each produced value is appended to the new list.
What do you think happens?
Suppose the outer input contains two inner lists, [1, 2] and [3, 4]. If a nested comprehension copies each inner value into one new list, which values appear first: 1 and 2, or 3 and 4?
Reveal answer
Answer: 1 and 2
The outer loop reaches the first inner list before it reaches the second. The inner loop processes all values in the first inner list, then the outer loop advances to the second inner list.
Tracing the Two Loops
numbers = [[1, 2], [3, 4]] flat_numbers = [number for group in numbers for number in group]
[1, 2, 3, 4]Reading the Comprehension Structure
The general list-comprehension pattern is [expression for item in list if condition]. The expression determines what is placed into the new list. The for-clause chooses the source values, and the optional condition determines which values are allowed through. In a nested comprehension, another for-clause supplies a second level of iteration. The order of the clauses describes the order of the corresponding loops: the outer source is named first, followed by the inner source.
| Part | Role |
|---|---|
| Expression | Calculates the value added to the new list |
| Outer for-clause | Chooses one inner collection at a time |
| Inner for-clause | Chooses values from the current inner collection |
| Optional condition | Allows only values that pass the condition |
| Result | A new list containing the collected expression results |
Transforming every inner value
Build a new list containing twice each value from the inner lists [[2, 3], [4]].
Choose the expression: The expression is value * 2, so every selected value is transformed before it is added.
Run the outer loop: The outer loop first selects [2, 3], then selects [4].
Run the inner loop: The inner loop visits 2 and 3, then visits 4.
Collect the results: The transformed values are 4, 6, and 8, in the order in which the inner values were visited.
[4, 6, 8]
[4, 6, 8]Mapping Inputs to Positions
A nested comprehension does not preserve the inner lists as separate containers when its expression produces individual values. Instead, each selected value contributes one item to the new list. The output position therefore records the traversal order: all selected values from the first inner list appear before the selected values from the next inner list.
What do you think happens?
What is the result of [item + 1 for row in [[1, 2], [5]] for item in row]?
Reveal answer
Answer: [2, 3, 6]
The outer loop selects [1, 2] first. The inner loop transforms 1 to 2 and 2 to 3. It then selects [5] and transforms 5 to 6.
Lambda Keys and New Lists
Lambda functions and list comprehensions can appear in the same exercise, but they perform different jobs. A lambda is a small unnamed function written inline. When it is supplied as the key to sort(), it receives each list element, transforms that element into a temporary comparison value, and lets sorting use that value. The original elements remain in their original form. A list comprehension, in contrast, creates a new list by transforming and optionally filtering source elements.
The point with x equal to 2 comes before the point with x equal to 4.Mistakes in Loop and Lambda Logic
Reversing the for-clauses
The inner value is used before group has been selected from the outer collection. The clause order no longer matches the intended outer-then-inner traversal.
Fix:
[value for group in groups for value in group]Expecting a nested comprehension to keep inner lists separate
The expression is value, so each individual value is collected into one new list rather than collecting the original groups as separate elements.
Fix:
Trace the expression separately from the loops. The expression decides what each output item is.Confusing a condition with a transformation
The condition decides whether a value is included; it does not place value * 2 into the result.
Fix:
Use [value * 2 for value in numbers] when the goal is to transform every selected value.Assuming a lambda sort key changes each element
The lambda returns a temporary value used for comparison. It does not replace each point dictionary with its x-coordinate.
Fix:
Keep the point as the list element and treat point['x'] as the sorting value.Ignoring syntax and clause order
These features rely on exact syntax, including the order of clauses and the complete expression returned by the lambda.
Fix:
Separate the expression, each for-clause, and any condition while debugging. Then trace one outer item and one inner item at a time.
When a nested comprehension feels difficult to read, expand its logic mentally into an outer loop, an inner loop, and an append operation. First identify the current outer item, then list the inner values it supplies, and finally apply the expression to each value. This step-by-step trace makes syntax errors and incorrect output predictions easier to locate.
Trace Before You Run
Predict the result of this comprehension before checking it: [number - 1 for row in [[3, 6], [10, 12]] for number in row]. Then write down the outer items in order, the inner values in order, and the transformed value produced for each one.
Hints
- The outer loop selects [3, 6] before [10, 12].
- The inner values are visited as 3, 6, 10, and 12.
- Apply number - 1 only after selecting each inner value.
A list contains point dictionaries. Explain what comparison value this key function produces for each point: lambda point: point['x']. Then describe how the list order changes when the points begin with x-values 4 and 2.
Hints
- The lambda receives one point at a time.
- It returns the point's x-coordinate.
- Compare 4 and 2 to determine which point comes first.
Key Takeaways
- A list comprehension creates a new list by transforming and optionally filtering source elements.
- In a nested comprehension, the outer loop selects an inner collection and the inner loop processes its values before the outer loop advances.
- The output order follows the loop order, so tracing each outer item and its inner values predicts the resulting list.
- A lambda used as a sort key returns a temporary comparison value; it does not replace the original list elements.
- When debugging, inspect syntax and then trace the expression, outer loop, inner loop, condition, and output collection separately.
Key Takeaways
- Nested list comprehensions combine an outer iteration with an inner iteration to build one new list.
- The first inner collection is fully processed before the outer loop moves to the next collection.
- The expression determines the value placed at each output position, while an optional condition filters which values are included.
- Lambda sort keys calculate temporary comparison values without changing the form of the original elements.
- Careful step-by-step tracing is the most reliable way to predict and debug comprehension behavior.