Matua Doc

Matua Doc

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 0 is the first row,
  • column 0 is 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:

  1. The full first row.
  2. The value in row 2, column 3.
  3. The value in row 3, column 1.
  4. 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:

  1. Return the sum of that column across all rows.
  2. Ignore rows that are too short to contain that column.
  3. 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:

  1. Return nil if the 2D array is empty.
  2. Use loops to determine which is the largest value in the arrays.
  3. Print a clear message for both the nil case 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 a Double version 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 rowAverage helper for Task A,
  • a printAllValues helper 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] and array[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.