Python Foundations

2D Arrays

Two-dimensional lists (matrices) — creating, initialising, accessing, changing, looping with nested loops, row/column operations, and reading from files. The grid data structure behind leaderboards, seating plans and spreadsheets.

9.1 Creating a 2D Array

A 2D array is a list of lists. The outer list holds the rows; each inner list is one row of values. Python does not have a built-in array type the way Cambridge pseudocode does — instead we use nested lists.

matrix = [
    [1, 2, 3],   # Row 0
    [4, 5, 6],   # Row 1
    [7, 8, 9]    # Row 2
]

print(matrix)
# Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
col 0col 1col 2
row 0123
row 1456
row 2789
Key idea:
  • The grid above has 3 rows and 3 columns — a 3×3 array.
  • Each inner list is one row.
  • The highlighted cell matrix[1][1] is row 1, column 1 = 5.

9.2 Initialising a 2D Array

There are six ways to fill a 2D array. Which one you choose depends on whether you already know the values, or whether you need a blank grid of a fixed size to fill in later.

1 — Static (values known in advance)

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

2 — Empty array (no data yet)

matrix = []  # add rows later with matrix.append(...)

3 — Fixed size, filled with zeros

rows = 3
cols = 4
matrix = [[0 for _ in range(cols)] for _ in range(rows)]
Key rule — never use [[0]*cols]*rows:
  • Build a fixed-size grid with a nested comprehension (one inner comprehension per row).
  • Never write [[0]*cols]*rows — that makes every row the same list object.
  • Changing one row then secretly changes them all.

4 — Fixed size, any default value

rows = 2
cols = 3
matrix = [["-" for _ in range(cols)] for _ in range(rows)]

5 — Fill from user input

rows = 2
cols = 3
matrix = []
for i in range(rows):
    row = []
    for j in range(cols):
        value = int(input("Enter value: "))
        row.append(value)
    matrix.append(row)

6 — Fill by reading a file

matrix = []
with open("data.txt", "r") as file:
    for line in file:
        row = [int(x) for x in line.strip().split(",")]
        matrix.append(row)
Your Turn — Declare a 2D array with a default value [3 marks]
Write program code to declare a 2D array jobs of 4 rows by 2 columns and initialise every element to -1.
Hint:
  • Set the size in named variables (rows = 4, cols = 2)
  • Use a nested comprehension so each row is its own list
  • The default value is -1 (an integer)
Your Turn
Write program code to declare a 2D array seats of 3 rows by 5 columns where every element is the string "Available".
Hint:
  • Same pattern as the zeros method
  • The default value is a string ("Available") instead of a number
  • Use a nested comprehension, never the * operator on the outer list
Exam tip:
  • The examiner gives marks for: (1) the correct size, (2) the correct starting value, and (3) using a loop/comprehension rather than typing the values by hand.
  • If the question says "initialised", a hand-typed list usually scores 0 for the initialisation mark.

9.3 Accessing Elements

To get one value you give the row index first, then the column index: matrix[row][col]. Both start counting at 0.

matrix = [
    [1, 2, 3],   # Row 0
    [4, 5, 6],   # Row 1
    [7, 8, 9]    # Row 2
]

print(matrix[0][1])   # row 0, col 1 -> 2
print(matrix[2][2])   # row 2, col 2 -> 9
Key rule — row first, column second:
  • matrix[a][b] means "go to row a, then move along to column b".
  • Swapping them gives a different cell (or an error if the grid is not square).
Your Turn — Accessing an element
State what grid[1][2] returns for the array grid = [[10,20,30],[40,50,60]], and explain how you found it.
Hint:
  • First index is 1 → go to row 1, which is [40,50,60]
  • Second index is 2 → take column 2 of that row
  • Count 0, 1, 2 → that is 60
Your Turn
State what grid[0][2] and grid[2][1] return for grid = [[5,6,7],[8,9,10],[11,12,13]].
Hint:
  • Work the row out first, then count along the columns from 0
  • grid[0][2]: row 0 is [5,6,7], column 2 is 7
  • grid[2][1]: row 2 is [11,12,13], column 1 is 12
Exam tip:
  • A very common slip is reading matrix[col][row] by habit.
  • Write a tiny note in the margin — "row first" — and check it on every access.
  • Examiners do not award the mark if the indices are the wrong way round.

9.4 Changing Elements

Assign a new value straight to the element using its two indices. This overwrites just that one cell — everything else stays exactly as it was.

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

matrix[1][1] = 50   # change the middle element 5 -> 50
print(matrix)
# Output: [[1, 2, 3], [4, 50, 6], [7, 8, 9]]
Key rule:
  • matrix[row][col] = newValue overwrites just that one cell.
  • Everything else stays exactly as it was.
Your Turn — Booking a seat
A seating grid seats = [["A","A","A"],["A","A","A"]] uses "A" for available. Write program code to book the seat in row 1, column 2 (set it to "X") and print the grid.
Hint:
  • Locate the cell: row 1, column 2
  • Assign the new value with seats[1][2] = "X"
  • Print the grid to verify
Your Turn
Using the same seats grid, write program code to book row 0, column 0, then print the result.
Hint:
  • Only one index pair changes from the worked example
  • Use seats[0][0] = "X"
  • Print the grid

9.5 Looping Through a 2D Array

The outer loop walks down the rows. For each row, the inner loop walks across its columns. After finishing a row, we print a newline to start the next one on a fresh line.

matrix = [[1, 2, 3], [4, 50, 6], [7, 8, 9]]

for row in matrix:          # each inner list
    for element in row:     # each value in that row
        print(element, end=" ")
    print()                 # newline after each row

# Output:
# 1 2 3
# 4 50 6
# 7 8 9
Key rule — when you need indices:
  • If you need the index numbers (not just the values), loop with range.
  • for i in range(len(matrix)) for rows, and for j in range(len(matrix[i])) for columns.
  • Use matrix[i][j] inside.
Your Turn — Total of all values
Write program code using a nested loop to find and print the total of all values in m = [[1,2,3],[4,5,6]].
Hint:
  • Start a running total at 0 before the loops
  • Outer loop over rows, inner loop over each value
  • Add each value to the total
  • Print the total after both loops finish
Your Turn
Write program code using a nested loop to find and print the largest value in m = [[3,9,2],[7,1,8]].
Hint:
  • Keep a variable biggest; start it at the first element (m[0][0])
  • Compare every value against it
  • If a value is bigger, update biggest
  • Print biggest after both loops finish
Your Turn — Count zeros
Count how many values in m = [[0,5],[5,0]] are 0.
Hint:
  • Counter at 0 before the loops
  • Add 1 each time a value equals 0
  • Loop through every row and every value
Your Turn
Count how many values in m = [[3,4],[8,2]] are greater than 3.
Hint:
  • Same counter pattern
  • Swap the condition to v > 3
  • Only 4 and 8 are greater than 3

9.6 Operations on a 2D Array

To work on whole rows, loop with an index i so you can grab the row as matrix[i] and use Python's sum() on it.

matrix = [[1, 2, 3], [9, 9, 9], [4, 0, 1]]

max_sum = -1
max_row = -1
for i in range(len(matrix)):
    row_sum = sum(matrix[i])
    if row_sum > max_sum:
        max_sum = row_sum
        max_row = i

print("Row", max_row, "has the highest sum:", max_sum)
# Output: Row 1 has the highest sum: 27
Key rule — rows vs columns:
  • sum(matrix[i]) totals one row.
  • To total a column you cannot use sum directly.
  • Loop over the rows and add matrix[i][j] for the fixed column j.
Your Turn — Total of column 0
Write program code to print the total of column 0 in m = [[1,2],[3,4],[5,6]].
Hint:
  • Fix the column at 0; start a total at 0
  • Loop over the rows with range(len(m))
  • Add m[i][0] for each row
  • Print the total (1+3+5 = 9)
Your Turn
Write program code to find the column with the highest total in m = [[1,5],[2,5],[3,5]] and print its index.
Hint:
  • Loop columns with j (range(len(m[0])))
  • For each j, total m[i][j] over all rows
  • Track the maximum like the row example
  • Column 0 = 1+2+3 = 6; column 1 = 5+5+5 = 15
Exam tip:
  • Start max_sum at a value below any possible total (often -1 or the first row's sum).
  • If you start it at 0 and every total could be 0 or negative, you may pick the wrong row.
  • The examiner checks that the maximum is initialised safely.

9.7 Reading a 2D Array from a File

Each line of the file becomes one row. Split the line on its separator, convert if needed, then append the row to the array.

# scores.txt:
# Musarrat,80,90,70
# Naib,85,75,95
# Mohar,78,88,82

data = []
with open("scores.txt", "r") as file:
    for line in file:
        parts = line.strip().split(",")
        name = parts[0]
        marks = [int(x) for x in parts[1:]]
        data.append([name] + marks)

print(data)
# Output: [['Musarrat', 80, 90, 70], ['Naib', 85, 75, 95], ['Mohar', 78, 88, 82]]
Key rule — always .strip() before splitting: Always .strip() each line before splitting, to remove the invisible newline character at the end — otherwise the last value carries a \n and number conversion fails.
Your Turn — Read from file with exception handling
Write a function read_data() that reads grid.txt (lines of space-separated integers) into a 2D array and returns it. Use exception handling around opening the file.
Hint:
  • Wrap the file work in try/except so a missing file does not crash
  • Build a row per line, convert to integers
  • Append each row to the grid
  • Return the grid; print a message on error
Your Turn
Write a function read_records() that reads players.txt (each line is name,score) into a 2D array where each row is [name, score] with the score as an integer. Return the array.
Hint:
  • Split on the comma
  • Keep element 0 as a string (name)
  • Convert element 1 with int() (score)
  • Append [name, score] to the records list

9.8 Full Exam-Style Question

A school stores student names and three subject marks (Math, English, Science) in a text file scores.txt. Each line is Name,Math,English,Science:

Musarrat,80,90,70
Tarnima,85,75,95
Aymaan,78,88,82
Mehrin,92,85,79
(a) — read_scores() [5 marks] Write program code for a function read_scores() that reads scores.txt into a 2D list studentData, where each row stores the name (string) followed by the three marks (integers), and returns the list.
(b) — calculate and display average [4 marks] Write program code that, for each student, calculates the average of the three marks, displays the name and average rounded to 2 decimal places.
(c) — write to averages.txt [4 marks] Write program code that writes each student's name, three marks and average to a new file averages.txt in the format Name,M,E,S,Average.
Your Turn — Model solution
Click Show Answer to see the full model solution for parts (a), (b) and (c).
Hint:
  • (a) Read file, strip + split each line, convert marks to int, append [name] + marks
  • (b) Loop through each row, average = (m1+m2+m3)/3, print name and round(average, 2)
  • (c) Open averages.txt in "w" mode, write each row as Name,M,E,S,Average with newline

Mark scheme

PartMarking points (1 mark each unless stated)
(a) [5]
  • Function header and returns the list studentData
  • Opens scores.txt for reading
  • Loops through every line of the file
  • Splits each line on the comma and strips the newline
  • Stores name as string and the three marks as integers in one row (append)
(b) [4]
  • Loops through every row of the 2D list
  • Adds the three marks for a student
  • Divides by 3 to get the average
  • Displays name with average rounded to 2 d.p. (round(avg, 2))
(c) [4]
  • Opens averages.txt for writing
  • Loops through every student record
  • Builds the line in the order Name,M,E,S,Average (any two correct fields)
  • Writes each record on its own line (newline included)

Key Points Summary

A 2D array is a list of lists — rows holding columns.
Access a cell with matrix[row][col]; indexing starts at 0. Row first, column second.
Change a cell with matrix[row][col] = newValue — only that cell changes.
Build a fixed-size grid with a nested comprehension, never [[0]*c]*r (shared references).
Six ways to initialise: static, empty, zeros, default value, user input, file.
Use a nested loop to visit every element — outer = rows, inner = columns.
sum(matrix[i]) totals a row; loop manually to total a column (add matrix[i][j] for fixed j).
Start max_sum below any possible total (e.g. -1) when finding the row/column with the highest sum.
To load from a file: read line by line, .strip().split(","), convert, append.
Always .strip() before splitting — the invisible \n corrupts the last value.
Examiners award marks for correct size, correct default value, and using a loop/comprehension.
For mixed-type rows (name + marks), keep the name as a string and convert marks with int().

9.9 Practice Tasks

Fifteen exam-style 2D array tasks. Each shows only the question — click Hint for the thought process, or Help for the worked solution.

Exam tip:
  • For every 2D array task, the marker checks: (1) correct creation/initialisation, (2) correct indexing (row first, column second), (3) correct nested loop structure, (4) correct use of sum() for rows or manual loop for columns.
  • The most common mark loss is using [[0]*c]*r instead of a nested comprehension.
1Practice Task — Create a 3×3 identity matrix [2 marks]
Write Python code to create a 3×3 2D array where the diagonal elements are 1 and all others are 0.
2Practice Task — Declare a 5×5 grid of zeros [2 marks]
Write Python code to declare a 5×5 2D array where every element is 0.
3Practice Task — Access an element [2 marks]
For grid = [[10,20,30],[40,50,60],[70,80,90]], state the value of grid[2][0].
4Practice Task — Change an element [2 marks]
For matrix = [[1,2,3],[4,5,6],[7,8,9]], write code to change the element at row 0, column 2 to 99, then print the matrix.
5Practice Task — Print the grid row by row [3 marks]
Write Python code using a nested loop to print a 3×3 grid matrix = [[1,2,3],[4,5,6],[7,8,9]] with each row on its own line, elements separated by spaces.
6Practice Task — Total of all values [3 marks]
Write Python code to find and print the total of all values in m = [[1,2,3],[4,5,6],[7,8,9]] using a nested loop.
7Practice Task — Find the maximum value [3 marks]
Write Python code to find and print the largest value in m = [[3,9,2],[7,1,8],[4,6,5]] using a nested loop.
8Practice Task — Count values above a threshold [3 marks]
Count how many values in m = [[5,10,3],[8,2,15],[1,20,7]] are greater than 5.
9Practice Task — Row with highest sum [4 marks]
For matrix = [[1,2,3],[9,9,9],[4,0,1]], write code to find and print the index of the row with the highest sum.
10Practice Task — Total of a column [3 marks]
Write Python code to print the total of column 1 in m = [[1,5],[2,5],[3,5]].
11Practice Task — Fill from user input [4 marks]
Write Python code to create a 2×3 2D array by asking the user to enter each integer value.
12Practice Task — Read CSV file into 2D array [5 marks]
Write a function read_data(filename) that reads a CSV file (each line is name,mark1,mark2) into a 2D array where marks are integers. Return the array.
13Practice Task — Count available seats [4 marks]
A 3×5 seating grid seats uses "A" for available and "X" for booked. Write code to count how many seats are still available.
14Practice Task — Book a seat with validation [5 marks]
Write a function book_seat(seats, row, col) that sets seats[row][col] to "X" only if the seat is currently "A". Return True if booked, False if already taken.
15Practice Task — Write 2D array to file [5 marks]
Write a function save_data(filename, data) that writes a 2D array to a file, one row per line, with values comma-separated.

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

A 2D array in Python is a:

Question 2True / False

In matrix[row][col], the row index comes before the column index.

Question 3Multiple Choice

Which correctly creates a 3×4 grid of zeros?

Question 4Multiple Choice

For grid = [[10,20,30],[40,50,60]], what is grid[0][2]?

Question 5True / False

[[0]*cols]*rows creates independent row lists.

Question 6Multiple Choice

How do you change the element at row 2, column 1 to 99?

Question 7Multiple Choice

In a nested loop over a 2D array, the outer loop walks the:

Question 8True / False

sum(matrix[i]) totals row i of a 2D array.

Question 9Multiple Choice

To total column j, you must:

Question 10Multiple Choice

When reading a 2D array from a file, what must you do to each line before splitting?

Question 11True / False

For "Musarrat,80,90,70", the correct way to get [80,90,70] as integers is [int(x) for x in parts[1:]].

Question 12Multiple Choice

When finding the row with the highest sum, max_sum should start at:

Answer all 12 questions to enable submission.