Working with Multidimensional Arrays in Swift

Updated: April 28, 2023 By: Khue Post a comment

Overview

In Swift, a multidimensional array (also known as a nested array or an array of arrays) is an array that contains other arrays as its elements. Some real-world use cases of multidimensional arrays in Swift are

  • Game or game-like app development: You can use multidimensional arrays to store the state of a game board, such as a chess board, a tic-tac-toe board, a minesweeper grid, etc. You can also use them to store the pixel data of an image or a sprite.
  • Data analysis: There might be cases where you would perform some calculations right in an iOS app rather than doing so on the server side. You can use multidimensional arrays to store the data from multiple sources or dimensions, such as a sales report, survey result, time series, etc. You can also use them to perform statistical operations such as mean, variance, correlation, etc
  • Scientific computing: You can use multidimensional arrays to store the values of a function or a variable over a domain, such as a temperature field, a pressure field, a velocity field, etc. You can also use them to solve partial differential equations using finite difference or finite element methods.
  • Machine learning: On-device machine learning is becoming more and more popular these days with the help of frameworks like PyTorch and TensorFlow. You can use multidimensional arrays to store the weights and biases of a neural network, the features, and labels of a dataset, the output of a convolutional layer, etc. You can also use them to perform matrix operations such as multiplication, transpose, inverse, etc.

Note: A two-dimensional array is often referred to as a matrix or a 2D array. A three-dimensional array is often referred to as a 3D array.

Creating and initializing multidimensional arrays

To create a multidimensional array in Swift, you can use nested brackets to indicate the type and dimensions of the array. For example, to create a two-dimensional array of integers, you can write [[Int]]. To create a three-dimensional array of strings, you can write [ [ [String] ] ], and so on.

Example:

// an empty two dimensional array of integers
var matrix = [[Int]]()
// add values to the array
matrix.append([1, 2, 3])
matrix.append([4, 5, 6])
print(matrix)
// Output: [[1, 2, 3], [4, 5, 6]]

// a 2D array with values
var otherMatrix = [[99,201],[322,448]]

Another example:

// a three dimensional array of strings
var threeDArray = [[[String]]]()
// add values to the array
threeDArray.append([["a", "b"], ["c", "d"]])
threeDArray.append([["e", "f"], ["g", "h"]])
print(threeDArray)
// Output: [[["a", "b"], ["c", "d"]], [["e", "f"], ["g", "h"]]]

To initialize a multidimensional array with repetitive values, you can use the Array class’s initializer that takes a repeating value and a count. For example, to create a two-dimensional array of integers with 5 rows and 5 columns, all filled with zeros, you can write:

// Sling Academy
// main.swift

var matrix: [[Int]] = Array(repeating: Array(repeating: 0, count: 5), count: 5)
print(matrix)

Output:

[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

This is very helpful when you need an array that contains a very large number of elements.

Access and modify elements of a multidimensional array

To access or modify an element of a Swift multidimensional array, you need to specify the indices for each dimension. For example, if you have a 2-D array called cinema that represents a cinema room with rows and columns of seats:

let cinema: [[String]] = [
    ["X", "X", "X", "X", "X", "X", "X", "X", "X", "X"],
    ["X", "O", "O", "O", "X", "O", "O", "O", "O", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "O", "O", "X", "O", "O", "O", "O", "X"],
    ["X", "X", "X", "X", "X", "X", "X", "X", "X", "X"],
]

Then you can access or modify the element at row 2 and column 3 by writing:

cinema[2][3]

You can use this expression to read or write the value of that element. For example, you can print the value by writing:

print(cinema[2][3])

Or you can change the value by writing:

cinema[2][3] = "Unknown"

Similarly, if you have a 3D array called cube that represents a cube with layers of grids:

var cube:[[[Int]]] = [
    [[1, 1, 1], [1, 1, 1], [1, 1, 1]],
    [[2, 2, 2], [2, 2, 2], [2, 2, 2]],
    [[3, 3, 3], [3, 3, 3], [3, 3, 3]],
    [[4, 4, 4], [4, 4, 4], [4, 4, 4]],
    [[5, 5, 5], [5, 5, 5], [5, 5, 5]],
    [[6, 6, 6], [6, 6, 6], [6, 6, 6]]
]

You can access or modify the element at layer 1, row 2, and column 3 by writing:

print(cube[1][2][2])

Or you can change the value by writing:

cube[1][2][3] = 9

If you do not provide an index for each dimension, you will retrieve an array rather than an individual value within the array.

Loop over a multidimensional array

To loop over a multidimensional array, you can use nested for loops to iterate over each dimension.

Example:

let cinema: [[String]] = [
    ["X", "X", "X", "X", "X", "X", "X", "X", "X", "X"],
    ["X", "O", "O", "O", "X", "O", "O", "O", "O", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "X", "O", "X", "O", "X", "O", "X", "X"],
    ["X", "O", "O", "O", "X", "O", "O", "O", "O", "X"],
    ["X", "X", "X", "X", "X", "X", "X", "X", "X", "X"],
]

for row in cinema {
    for seat in row {
        print(seat, terminator: " ")
    }
    print("")
}

Output:

X X X X X X X X X X 
X O O O X O O O O X 
X O X O X O X O X X 
X O X O X O X O X X 
X O X O X O X O X X 
X O X O X O X O X X 
X O X O X O X O X X 
X O X O X O X O X X 
X O O O X O O O O X 
X X X X X X X X X X 

Using high-order functions with a multidimensional array

You can use higher-order functions like map(), filter(), reduce(), etc. to manipulate multidimensional arrays in Swift.

For example, suppose you have a 3-D array called colors that represents the RGB values of pixels in an image. Each layer represents a color channel (red, green, or blue) and each grid represents a pixel. You want to convert the image to grayscale by averaging the RGB values of each pixel. You can use the map() function to apply a function that calculates the average of an array to each pixel of the 3-D array as shown below:

var colors = [[[255, 0, 0], [0, 255, 0]], [[0, 0, 255], [255, 255, 255]]]
var grayscale = colors.map { layer in
    layer.map { pixel in
        pixel.reduce(0, +) / pixel.count
    }
}

print(grayscale)

Output:

[[85, 85], [85, 255]]

Flattening a multidimensional array

Flattening a multidimensional array means converting it to a one-dimensional array by concatenating all the elements of the subarrays. For example, flattening a 2-D array like this:

[[1, 2], [3, 4], [5, 6]]

This would result in a 1-D array like this:

[1, 2, 3, 4, 5, 6]

To flatten a multidimensional array in Swift, you can use the joined() method on the array. This method returns a sequence of all the elements of the subarrays in order. You can then convert this sequence to an array by using the Array initializer.

Example:

var matrix = [[1, 2], [3, 4], [5, 6]]
var flat = Array(matrix.joined())
print(flat)

Output:

[1, 2, 3, 4, 5, 6]