{"assignment":{"_schema_version":2,"course_id":37,"date_created":"2022-06-28T19:00:00+00:00","date_modified":"2023-09-10T14:18:29.537713+00:00","extra_instructor_files":"","extra_starting_files":"","forked_id":null,"forked_version":null,"hidden":false,"id":1116,"instructions":"## Lists of Lists\n\n```python list-of-lists\nnumbers = [\n  [1, 2, 3, 5, 6],\n  [7, 8, 9, 10, 11],\n  [12, 13, 14, 15, 16],\n  [17, 18, 19, 20, 21],\n]\n\n# Entire nested list\nprint(numbers)\n# Third row of values\nprint(numbers[2])\n# First row, second column's value\nprint(numbers[0][1])\n```\n\nA common pattern is to store data, especially numeric data, in a list of lists.\nThis structure is like the tables that we saw with nesting dataclasses in lists.\nExcept now, every item inside the table cells must be the same type.\nStructurally, the inner lists all have the same element type: a primitive type.\nThe outer list has a somewhat complex element type: a list of primitives.\nThat means the type of the entire outer value is a list of lists of primitives.\nFolks sometimes refer to these as a \"matrix,\" a \"grid,\" or a \"2-dimensional\" list of numbers.\nThe representation is very useful for representing X- and Y-coordinate data.\n\n## Nested Iteration\n\n```python nested-iteration\nnumbers = [\n  [1, 2, 3, 5, 6],\n  [7, 8, 9, 10, 11],\n  [12, 13, 14, 15, 16],\n  [17, 18, 19, 20, 21],\n]\n\n# Iterate through outer list\nfor row in numbers:\n    # Iterate through inner list\n    for number in row:\n        # Reached actual integer\n        print(number)\n```\n\nFrequently, you will want to loop over the data, just like we did with one-dimensional lists.\nTo do so, we need to nest the `for` loops as shown.\nIn this example, notice how when we iterate through the outermost list, we get a `row` for each element.\nThen we can iterate through each `row` to get each `number`.\nThe innermost body of the nested loops represents one individual element.\nThe `numbers` variable is holding a `list[list[int]]`, which means that the `row` will become a `list[int]` (the element type of the outer list).\nThe `number` variable will then be an `int`, since that is the element type of the inner list.\n\n## Nested Accumulate\n\n```python nested-sum\nnested = [[4, 6, 8],\n          [3, 5, 3]]\n\ntotal = 0\nfor row in nested:\n    row_total = 0\n    for value in row:\n        row_total = row_total + value\n    total = total + row_total\nprint(total)\n```\n\nDoing something with the individual elements, however, requires state outside of the loops.\nMuch like how our loop patterns had an additional variable outside of the loop, we require additional variables outside of both loops depending on what we are trying to do.\nIn the following code, we are adding up all the numbers in the list, first by iterating through row and summing their values, while adding together all those nested sums.\nTechnically, in this case, we could have added directly to the `total` variable, but we will soon see another example where we MUST have inner accumulation variables.\n\n## Nested Map\n\n```python nested-map\ndef double_table(table: list[list[int]]) -> list[list[int]]:\n  new_list = []\n  for row in table:\n      new_row = []\n      for value in row:\n          new_row.append(value * 2)\n      new_list.append(new_row)\n  return new_list\n\nprint(double_table([[4, 6, 8],\n                    [3, 5, 3]]))\n```\n\nIn this function `double_table`, we are implementing the nested map pattern by iterating through the list of lists of integers given.\nFor each row, we must create a `new_row`.\nWe also need to append each `new_row` to a `new_list` in each of the outermost iterations.\nWhen we are done, we'll have perfectly recreated the original structure, but this time each of the original numbers will have been doubled.\n\n## Nested Find\n\n```python nested-find\nnested = [[4, 6, 8],\n          [3, 5, 3]]\n\nfound = None\nfor row in nested:\n    for value in row:\n        if value > 5:\n            found = value\nprint(found)\n```\n\nIn this last nested loop pattern, we see a modification of the find pattern where we find the last value greater than 5.\nWe are once again iterating through each and then through each element within that row.\nWith the `if` statement inside of the innermost `for` loop, we ask a question about each individual element.\nBecause we are seeking a property about the entire table and not just within each row, we can use the same `found` variable throughout the entire nested iteration.\n\n## X/Y Iteration\n\n```python x-y-iteration\ngrid = [\n  [1, 2, 3, 5, 6],\n  [7, 8, 9, 10, 11],\n  [12, 13, 14, 15, 16],\n  [17, 18, 19, 20, 21],\n]\n\nfor y, row in enumerate(grid):\n    for x, value in enumerate(row):\n        print(x, y, value)\n```\n\nCombining what we have learned about iterating through indexes with what we know now about iterating through 2-dimensional lists, we can iterate through the indexes of the grid of data to get access to the X- and Y-positions within the table.\nNote how we iterate vertically through the table in the outermost loop, meaning that each index represents the `y` coordinate in the table.\nThe inner loop iterates within a row, so that represents the column or `x` coordinate.\nInside the loops, we have access to each individual x- and y-coordinate.\n\n## X/Y Access and Update\n\n```python x-y-update\ngrid = [\n  [1, 2, 3, 5, 6],\n  [7, 8, 9, 10, 11],\n  [12, 13, 14, 15, 16],\n  [17, 18, 19, 20, 21],\n]\n\n# Read third row, second column\nprint(grid[2][1])\n\n# Write third row, second column\ngrid[2][1] = 100\nprint(grid[2][1])\n```\n\nInstead of iterating by position, we can also access and update specific values within the grid by chaining together the indexing notation.\nThis is like how we chain together attribute accesses or method calls.\nEach time we reach another layer of data, we must unpack the information with another index.\nThe expression `grid[2]` gives a list, so we can unpack that with another indexing by having `grid[2][1]`.\nMuch like how we iterated vertically and then horizontally, it's important to remember that the indexing happens with the Y-axis first, then the X-axis second.\n\n## Decomposing Grids\n\n```python decomposition\ndef sum_row(numbers: list[int]) -> int:\n    total = 0\n    for number in numbers:\n        total = total + number\n    return total\n\ndef map_sum(grid: list[list[int]]) -> list[int]:\n    result = []\n    for row in grid:\n        result.append(sum_row(row))\n    return result\n\nprint(map_sum([\n  [1, 2, 3, 5, 6],\n  [7, 8, 9, 10, 11],\n  [12, 13, 14, 15, 16],\n  [17, 18, 19, 20, 21],\n]))\n```\n\nDecomposing complex grid-handling functions with a helper function is a smart way to make complicated code easier to read.\nInstead of trying to do two different loops, we can have one of the helper functions in a separate loop.\nThis example shows how we can turn a list of lists of integers into a single list of integers by mapping a sum function to each row.\nThis same idea can be applied to many other 2D list operations.\n\n## Summary\n\n- Lists can be nested inside of other lists, just like any other type.\n- Nested lists can be described as \"2-dimensional lists\" or \"grids.\"\n- The element type of the outer nested list is a list of primitive values.\n- To iterate over a nested list, you must nest a `for` loop inside of a `for` loop.\n- Similarly, the `for` loop patterns can be adapted to nested lists by nesting layers of `for` loops.\n- You can iterate over the indexes of a 2-dimensional list just like you can with a regular list.\n- You can index and update specific elements of a 2-dimensional list by chaining indexing.\n- Helper functions can decompose complex 2-dimensional nested `for` loop operations.\n\n","ip_ranges":"","name":"8B1) Nested Lists Reading","on_change":"","on_eval":"","on_run":"","owner_id":1,"owner_id__email":"acbart@udel.edu","points":0,"public":true,"reviewed":false,"sample_submissions":[],"settings":"{\n  \"header\": \"Nesting Lists\",\n  \"youtube\": {\n    \"Bart\": \"57sGMXQylNg\",\n    \"Amy\": \"Ew4uLGE93CQ\"\n  },\n  \"video\": {\n    \"Bart\": \"https://blockpy.cis.udel.edu/videos/bakery_nesting_2d_lists-Bart.mp4\",\n    \"Amy\": \"https://blockpy.cis.udel.edu/videos/bakery_nesting_2d_lists-Amy.mp4\"\n  },\n  \"summary\": \"\",\n  \"small_layout\": true\n}","starting_code":"","subordinate":true,"tags":[],"type":"reading","url":"bakery_nesting_2d_lists_read","version":12},"ip":"216.73.216.157","submission":{"_schema_version":3,"assignment_id":1116,"assignment_version":12,"attempts":0,"code":"","correct":false,"course_id":37,"date_created":"2026-05-20T14:01:39.927809+00:00","date_due":"","date_graded":"","date_locked":"","date_modified":"2026-05-20T14:01:39.927809+00:00","date_started":"","date_submitted":"","endpoint":"","extra_files":"","feedback":"","grading_status":"NotReady","id":2036898,"score":0.0,"submission_status":"Started","time_limit":"","url":"submission_url-22d7e2f2-2a01-42a6-819e-a70d9f12c898","user_id":2044668,"user_id__email":"","version":0},"success":true}
