This article is a translation of Swift Algorithm Club.

Swift Algorithm Club is an open source project produced by Raywenderlich.com to realize algorithms and data structures by Swift. Currently, there are 18000+⭐️ on GitHub. I have made a brief statistics, and there are about 100 algorithms and data structures. It’s basically a good resource for iOSer learning algorithms and data structures.

🐙andyRon/ swift-algorithm-club-CN is my project of learning and translating for Swift Algorithm Club. Due to the limited capacity, if you find any errors or improper translation, please correct them. Welcome to Pull Request. Also welcome interested, have time partners to participate in translation and learning 🤓. Of course, we welcome ⭐️, 🤩🤩 ️ ⭐ ⭐.

A translation of this article and the code can be found at 🐙swift-algorithm-club-cn/Array2D


In C and Objective-C, you can write the following code,

int cookies[9][7];
Copy the code

Make cookies on a 9×7 grid. This creates a two-dimensional array of 63 elements. To find cookies in columns 3 and 6, you can write:

myCookie = cookies[3][6];
Copy the code

This code does not work in Swift. To create a multidimensional array in Swift, you can write:

var cookies = [[Int]] ()for _ in 1.9 {
  var row = [Int] ()for _ in 1.7 {
    row.append(0)
  }
  cookies.append(row)
}
Copy the code

Then, to find cookies, you can write:

let myCookie = cookies[3] [6]
Copy the code

You can also create the above array with one line of code:

var cookies = [[Int]](repeating: [Int](repeating: 0.count: 7), count: 9)
Copy the code

This seems complicated, but you can simplify it by using helper functions:

func dim<T>(_ count: Int, _ value: T)- > [T] {
  return [T](repeating: value, count: count)}Copy the code

Dim is an abbreviation of dimension.

Then, you can create arrays like this:

var cookies = dim(9, dim(7.0))
Copy the code

Swift concludes that the data type of the array must be Int because you specified 0 as the default value for the array element. To use string arrays, you can write:

var cookies = dim(9, dim(7."yum"))
Copy the code

The dim() function makes it easier to create arrays of more dimensions:

var threeDimensions = dim(2, dim(3, dim(4.0)))
Copy the code

The disadvantage of using multidimensional arrays or multiple nested arrays in this way is that you can’t keep track of which dimensions represent what.

However, you can create your own type, which acts like a two-dimensional array and is easier to use:

public struct Array2D<T> {
  public let columns: Int
  public let rows: Int
  fileprivate var array: [T]
  
  public init(columns: Int, rows: Int, initialValue: T) {
    self.columns = columns
    self.rows = rows
    array = .init(repeating: initialValue, count: rows*columns)
  }
  
  public subscript(column: Int, row: Int) - >T {
    get {
      precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      return array[row*columns + column]
    }
    set {
      precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      array[row*columns + column] = newValue
    }
  }
}
Copy the code

The prefeed (_:_: FILE :line:) function is like assert, and satisfying the condition causes premature termination of the program and throws an error message, looking at the official documentation in detail. When the subscript exceeds the range, the effect is as follows:

Array2D is a generic, so it can support all types of objects, not just numbers

Create Array2D sample code:

var cookies = Array2D(columns: 9, rows: 7, initialValue: 0)
Copy the code

By using the subscript function, you can retrieve an object from an array:

let myCookie = cookies[column, row]
Copy the code

Or set the object:

cookies[column, row] = newCookie
Copy the code

Internally, Array2D uses a single one-dimensional array to store data. The index of the objects in this array is given by (Row x numberOfColumns) + column, but as a user of Array2D, you only need to consider columns and rows, and Array2D will do the actual events. This is the advantage of wrapping primitive types into a wrapper class or structure.

Translated by Andy Ron proofread by Andy Ron