runtime
83 / 250
lesson 83 Nested Data Structures · intermediate

Walk lists inside records

An order holds a list of line items; a push event holds a list of commits. A loop inside a loop visits every inner item, with the outer record still at hand.

You'll be able to
  • Write an outer loop over records and an inner loop over the list each record holds
  • Use fields of the outer record while visiting the inner items
  • Put an accumulator before the outer loop so it collects across every record
The idea

An order isn't one product: it's a record with its own fields and a list of line items. To answer *how many units of each product did we sell?* you must visit every line of every order.

That is a loop inside a loop. The outer loop takes one record at a time; the inner loop walks the list stored in that record. Inside the inner loop, both the line item and its order are available.

Run each example to see what it prints. Running examples doesn't count toward progress.

example-1.py · Every line of every order
orders = [
    {"order_id": "O100282", "items": [{"sku": "P0164", "qty": 2}, {"sku": "P0594", "qty": 1}]},
    {"order_id": "O100918", "items": [{"sku": "P0209", "qty": 3}]},
]
for order in orders:
    print(order["order_id"])
    for item in order["items"]:
        print(f"  {item['sku']} x {item['qty']} (order {order['order_id']})")

A classic slip is looping over the record instead of its list. A for over a dictionary visits its keys, which are text, so the next lookup fails.

example-2.py · Looping over the record, not its list
order = {"order_id": "O100282", "items": [{"sku": "P0164", "qty": 2}]}
for item in order:
    print(item)
    print(item["sku"])

To collect across all records, the accumulator goes before the outer loop. Then each inner pass adds to the same dictionary, and the result covers every order.

example-3.py · Units sold per product
def units_per_sku(orders):
    units = {}
    for order in orders:
        for item in order["items"]:
            sku = item["sku"]
            if sku not in units:
                units[sku] = 0
            units[sku] += item["qty"]
    return units

orders = [
    {"order_id": "O100282", "items": [{"sku": "P0164", "qty": 2}, {"sku": "P0594", "qty": 1}]},
    {"order_id": "O100918", "items": [{"sku": "P0164", "qty": 3}]},
    {"order_id": "O101219", "items": []},
]
print(units_per_sku(orders))

When to use it: orders and their lines, invoices and their charges, events and their payload lists, students and their scores. Mistakes to avoid: looping over the record instead of its list; creating the accumulator inside the outer loop, so each record wipes out the last; and return inside the outer loop, which stops after the first record.

Review
  • Outer loop over records, inner loop over the list each record holds; the outer record is still available inside.
  • A for over a dictionary visits its keys. Loop over the list stored under a key instead.
  • Accumulators that cover every record start before the outer loop.
  • Next: flatten nested records into plain rows, the shape spreadsheets and CSV files need.
Practise this

Loading your progress…

To master this lesson, solve both challenges without hints or the answer, and pass the concept check.

Walk lists inside records — Nested Data Structures · Runtime