Swift multi-dimensional arrays
Learning intentions
In this lesson, you will learn how multi-dimensional arrays store grouped data in rows and columns.
- Explain what a 2D array is,
- access values inside inner arrays using indexes,
- and write functions that accept 2D arrays as parameters.
You will also practise safe indexing and loop patterns for nested data.
- Use row and column indexes correctly,
- and avoid common out-of-range mistakes.
What is a multi-dimensional array?
A multi-dimensional array is an array that contains other arrays as its elements.
- In Level 2, the most common case is a 2D array,
- where each inner array represents one row of related values.
let scores = [
[78, 82, 91],
[65, 70, 68],
[88, 94, 90]
]
This scores variable is an [[Int]] because each row is [Int] and the outer container is an array of those rows.
Why use 2D arrays?
2D arrays are useful when data naturally fits a grid shape.
- Classroom scores by student and test,
- seating plans by row and seat number,
- or weekly measurements by day and time block.
They keep grouped values together so calculations are easier to organize.
Accessing inner arrays and items
Use two index steps: first choose the row, then choose the item in that row.
array[row]gives one inner array,array[row][column]gives one specific value.
let scores = [
[78, 82, 91],
[65, 70, 68],
[88, 94, 90]
]
let firstRow = scores[0] // [78, 82, 91]
let value = scores[2][1] // 94
print(firstRow)
print(value)
Understanding row and column indexes
Swift indexes start at 0, not 1.
- Row
0is the first row, - column
0is the first item inside that row.
let grid = [
[10, 20, 30],
[40, 50, 60]
]
print(grid[0][0]) // 10
print(grid[1][2]) // 60
Looping through a 2D array
Use nested loops to process every value.
- The outer loop visits each row,
- and the inner loop visits each item in that row.
let grid = [
[1, 2, 3],
[4, 5, 6]
]
for row in grid {
for value in row {
print(value)
}
}
Writing functions that accept 2D arrays
A function can accept a 2D array by using a parameter type like [[Int]] or [[Double]].
- This keeps your logic reusable,
- because the same function can process many different grids.
func total(of matrix: [[Int]]) -> Int {
var sum = 0
for row in matrix {
for value in row {
sum += value
}
}
return sum
}
let marks = [
[5, 4, 3],
[2, 4, 5]
]
print(total(of: marks)) // 23
Returning one row total from a function
You can also write functions that calculate totals for one chosen row.
- Pass in the 2D array,
- pass in a row index,
- and return the computed result.
func rowTotal(in matrix: [[Int]], row: Int) -> Int {
guard row >= 0 && row < matrix.count else { return 0 }
return matrix[row].reduce(0, +)
}
This guard check prevents out-of-range access when the row index is invalid.
Task A
Create a 2D array called temperatures with 3 rows and 4 values per row.
Print:
- The full first row.
- The value in row 2, column 3.
- The value in row 3, column 1.
- The average temperature of row 2.
Task B
Write nested loops to print every value in this 2D array:
let table = [
[2, 4, 6],
[8, 10, 12],
[14, 16, 18]
]
After printing all values, print one final line that shows how many total values were printed.
Task C
Write a function called columnTotal(in table: [[Int]], column: Int) that accepts [[Int]] and an Int column index.
Use this sample data (notice the rows have different lengths):
let table = [
[3, 5, 7, 9],
[2, 4],
[8, 6, 1],
[10]
]
Requirements:
- Return the sum of that column across all rows.
- Ignore rows that are too short to contain that column.
- Test your function with at least two different column indexes.
Task D
Write a function called maxValue(in:) that accepts [[Double]] and returns the largest value.
Use this sample data where some rows have fewer items:
let readings = [
[1.5, 3.2, 2.8],
[7.1],
[4.4, 6.0],
[5.9, 8.3, 0.7, 2.2]
]
Requirements:
- Return
nilif the 2D array is empty. - Use loops to determine which is the largest value in the arrays.
- Print a clear message for both the
nilcase and the normal case.
Extension for Super Players!
Improve all of your Task A to Task D solutions by adding one reusable safety layer for 2D arrays.
- Write a helper like
valueAt(_ table: [[Int]], row: Int, column: Int) -> Int?(and aDoubleversion for Task D), - Use it wherever you currently do direct indexing such as
table[row][column], - Print clear messages when a row or column does not exist instead of crashing.
Then refactor your code so repeated logic is moved into small helper functions.
- Example: a
rowAveragehelper for Task A, - a
printAllValueshelper for Task B, - and shared validation checks used by Tasks C and D.
Summary
Multi-dimensional arrays let you model grid-like data in Swift using arrays inside arrays.
- Access values with
array[row][column], - use nested loops to process all values,
- and write reusable functions with parameters like
[[Int]].
These patterns make your code cleaner and more scalable when data has row-and-column structure.
Review
Check your understanding with these prompts.
- Explain the difference between
array[row]andarray[row][column], - describe why nested loops are useful for 2D arrays,
- write one function signature that accepts
[[Double]], - and explain one way to avoid index-out-of-range errors.