{"id":"more-lists-nested","slug":"lists-in-lists","title":"Lists inside lists","text":"The items of a list can be lists themselves:\n\n```python\nteams = [[\"Ana\", \"Ben\"], [\"Cleo\", \"Dev\", \"Eli\"], [\"Finn\"]]\nprint(teams)\nprint(teams[1])\nprint(teams[1][0])\nprint(len(teams), len(teams[1]))\n```\n\n```output\n[['Ana', 'Ben'], ['Cleo', 'Dev', 'Eli'], ['Finn']]\n['Cleo', 'Dev', 'Eli']\nCleo\n3 3\n```\n\nRead `teams[1][0]` from left to right: `teams[1]` is the second team, which is a list, and `[0]` picks the first name in that list. The outer list has three items, and each of them happens to be a list.\n\n### A list as a record\n\nA short list can also hold the facts about one thing, each at its own index. For a book, the title could be at index 0, the year at index 1 and the number of pages at index 2:\n\n```python\n[\"The Glass Garden\", 2011, 312]\n```\n\nA list of such lists is a small database. A `for` loop goes through it one record at a time:\n\n```python\nbooks = [\n    [\"The Glass Garden\", 2011, 312],\n    [\"Night Trains\", 1998, 205],\n    [\"River of Salt\", 2020, 448],\n]\n\nfor book in books:\n    title = book[0]\n    year = book[1]\n    pages = book[2]\n    print(f\"{title} ({year}), {pages} pages\")\n```\n\n```output\nThe Glass Garden (2011), 312 pages\nNight Trains (1998), 205 pages\nRiver of Salt (2020), 448 pages\n```\n\nOn each round, `book` is one of the inner lists. Copying its items into variables with clear names makes the rest of the loop easy to read.\n\nAdding a record is an `append` of a whole list. Finding the best record works as it did with plain numbers, except that you compare one item of each record and keep the whole record:\n\n```python\nbooks = [\n    [\"The Glass Garden\", 2011, 312],\n    [\"Night Trains\", 1998, 205],\n    [\"River of Salt\", 2020, 448],\n]\nbooks.append([\"Paper Moons\", 1987, 260])\n\noldest = books[0]\nfor book in books:\n    if book[1] < oldest[1]:\n        oldest = book\n\nprint(\"Oldest:\", oldest[0], oldest[1])\n```\n\n```output\nOldest: Paper Moons 1987\n```\n\nThe weak spot of such a record is that you have to remember what each index means: nothing in `book[2]` says \"pages\". The dictionaries, a little later in this part, give each value a name instead.\n","task":"Each pet is a list of its name, its kind and its age. Fill in the blanks so the program prints:\n\n```\nRex is a dog, 4 years old\nTom is a cat, 7 years old\nPolly is a parrot, 12 years old\n```\n","kind":"fill","seed":"pets = [\n    [\"Rex\", \"dog\", 4],\n    [\"Tom\", \"cat\", 7],\n    [\"Polly\", \"parrot\", 12],\n]\n\nfor pet in pets:\n    name = pet[[[0]]]\n    kind = pet[[[1]]]\n    age = pet[[[2]]]\n    print(f\"{name} is a {kind}, {age} years old\")\n","solution":"pets = [\n    [\"Rex\", \"dog\", 4],\n    [\"Tom\", \"cat\", 7],\n    [\"Polly\", \"parrot\", 12],\n]\n\nfor pet in pets:\n    name = pet[0]\n    kind = pet[1]\n    age = pet[2]\n    print(f\"{name} is a {kind}, {age} years old\")\n","hints":["On each round of the loop, `pet` is one inner list, such as `[\"Rex\", \"dog\", 4]`.","The name is at index 0, the kind at index 1 and the age at index 2."],"tests":[{"name":"Output","stdin":"","expect":"Rex is a dog, 4 years old\nTom is a cat, 7 years old\nPolly is a parrot, 12 years old","hidden":false}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"groups = [[4, 7], [1, 5, 9], [2]]\nprint(groups[1])\nprint(groups[1][2])\nprint(len(groups))\nprint(groups[2][0] * groups[0][0])\n","solution":"groups = [[4, 7], [1, 5, 9], [2]]\nprint(groups[1])\nprint(groups[1][2])\nprint(len(groups))\nprint(groups[2][0] * groups[0][0])\n","hints":["`groups[1]` is the second inner list, and Python prints it with its brackets.","`groups[1][2]` is the third number of that inner list.","`len(groups)` counts the inner lists, not the numbers in them. `groups[2][0]` is 2 and `groups[0][0]` is 4."],"tests":[{"name":"Output","stdin":"","expect":"[1, 5, 9]\n9\n3\n8","hidden":false}],"require":[],"forbid":[],"lines":["[1, 5, 9]","9","3","8"]},{"task":"A shopping cart is a list of items, and each item is a list of a product's name, its price and the quantity: `[\"milk\", 1.25, 2]` is two bottles of milk at 1.25 each.\n\nWrite a function `total_price(cart)` that returns the total price of the cart. For example, `total_price([[\"milk\", 1.25, 2], [\"bread\", 2.5, 1]])` returns `5.0`.\n","kind":"code","seed":"def total_price(cart: list) -> float:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(total_price([[\"milk\", 1.25, 2], [\"bread\", 2.5, 1]]))\n","solution":"def total_price(cart: list) -> float:\n    total = 0\n    for item in cart:\n        price = item[1]\n        quantity = item[2]\n        total += price * quantity\n    return total\n\n\nif __name__ == \"__main__\":\n    print(total_price([[\"milk\", 1.25, 2], [\"bread\", 2.5, 1]]))\n","hints":["Go through the cart with a `for` loop. On each round the loop variable is one item, such as `[\"milk\", 1.25, 2]`.","The price is at index 1 and the quantity at index 2. Their product is what that item costs.","Add each item's cost to a total that starts at 0, and return the total after the loop."],"tests":[{"name":"total_price([[\"milk\", 1.25, 2], [\"bread\", 2.5, 1]])","stdin":"","call":"total_price([[\"milk\", 1.25, 2], [\"bread\", 2.5, 1]])\n","expect":"5.0","hidden":false,"returns":true},{"name":"total_price([[\"apples\", 0.75, 4], [\"cheese\", 6.5, 1], [\"tea\", 3.25, 2]])","stdin":"","call":"total_price([[\"apples\", 0.75, 4], [\"cheese\", 6.5, 1], [\"tea\", 3.25, 2]])\n","expect":"16.0","hidden":true,"returns":true},{"name":"total_price([[\"pen\", 1.5, 3]])","stdin":"","call":"total_price([[\"pen\", 1.5, 3]])\n","expect":"4.5","hidden":true,"returns":true}],"require":[],"forbid":[]}]}