【譯】Swift演算法俱樂部-二維陣列

Andy_Ron發表於2019-02-27

本文是對 Swift Algorithm Club 翻譯的一篇文章。

Swift Algorithm Clubraywenderlich.com網站出品的用Swift實現演算法和資料結構的開源專案,目前在GitHub上有18000+⭐️,我初略統計了一下,大概有一百左右個的演算法和資料結構,基本上常見的都包含了,是iOSer學習演算法和資料結構不錯的資源。

?andyRon/swift-algorithm-club-cn是我對Swift Algorithm Club,邊學習邊翻譯的專案。由於能力有限,如發現錯誤或翻譯不妥,請指正,歡迎pull request。也歡迎有興趣、有時間的小夥伴一起參與翻譯和學習?。當然也歡迎加⭐️,?????。

本文的翻譯原文和程式碼可以檢視?swift-algorithm-club-cn/Array2D


在C和Objective-C中,您可以編寫下面程式碼,

int cookies[9][7];
複製程式碼

製作9×7網格的cookies。 這將建立一個包含63個元素的二維陣列。 要在第3列和第6行找到cookie,您可以寫:

myCookie = cookies[3][6];
複製程式碼

這段程式碼在Swift中不能成立的。 要在Swift中建立一個多維陣列,您可以編寫:

var cookies = [[Int]]()
for _ in 1...9 {
  var row = [Int]()
  for _ in 1...7 {
    row.append(0)
  }
  cookies.append(row)
}
複製程式碼

然後,要查詢cookie,您可以寫:

let myCookie = cookies[3][6]
複製程式碼

您還可以使用一行程式碼中建立上面的陣列:

var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9)
複製程式碼

這看起來很複雜,但您可以使用輔助函式簡化它:

func dim<T>(_ count: Int, _ value: T) -> [T] {
  return [T](repeating: value, count: count)
}
複製程式碼

譯註:這邊的dim,應該是dimension(維度)的縮寫。

然後,你可以這樣建立陣列:

var cookies = dim(9, dim(7, 0))
複製程式碼

Swift推斷陣列的資料型別必須是Int,因為您指定了0作為陣列元素的預設值。 要使用字串陣列,您可以編寫:

var cookies = dim(9, dim(7, "yum"))
複製程式碼

dim()函式可以更容易地建立更多維度的陣列:

var threeDimensions = dim(2, dim(3, dim(4, 0)))
複製程式碼

以這種方式使用多維陣列或多個巢狀陣列的缺點是無法跟蹤什麼維度代表什麼。

然而,您可以建立自己的型別,其作用類似於二維陣列,使用起來更方便:

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
    }
  }
}
複製程式碼

譯註:precondition(_:_:file:line:)函式類似assert,滿足條件會造成程式的提前終止並丟擲錯誤資訊,詳細檢視官方文件。此處有來表示當下標超過範圍的提示,效果如下:

【譯】Swift演算法俱樂部-二維陣列

Array2D是一個泛型,因此能夠支援所有型別物件,而不是隻能是數字

建立Array2D示例程式碼:

var cookies = Array2D(columns: 9, rows: 7, initialValue: 0)
複製程式碼

通過使用下標函式,您可以從陣列中檢索一個物件:

let myCookie = cookies[column, row]
複製程式碼

或者設定物件:

cookies[column, row] = newCookie
複製程式碼

在內部,Array2D使用單個一維陣列來儲存資料。 該陣列中物件的索引由(row x numberOfColumns) + column給出,但作為Array2D的使用者,您只需要考慮columnrow,具體事件將 由Array2D完成。 這是將基本型別包裝成包裝類或結構中的優點。

作者: Matthijs Hollemans
翻譯:Andy Ron
校對:Andy Ron

相關文章