[英]Two-dimensional array in Swift
我對 Swift 中的二維數組感到非常困惑。 讓我一步一步描述。 如果我錯了,請您糾正我。
首先; 空數組的聲明:
class test{
var my2Darr = Int[][]()
}
其次填充數組。 (例如my2Darr[i][j] = 0
其中 i, j 是 for 循環變量)
class test {
var my2Darr = Int[][]()
init() {
for(var i:Int=0;i<10;i++) {
for(var j:Int=0;j<10;j++) {
my2Darr[i][j]=18 /* Is this correct? */
}
}
}
}
最后,編輯數組中的元素
class test {
var my2Darr = Int[][]()
init() {
.... //same as up code
}
func edit(number:Int,index:Int){
my2Darr[index][index] = number
// Is this correct? and What if index is bigger
// than i or j... Can we control that like
if (my2Darr[i][j] == nil) { ... } */
}
}
// 2 dimensional array of arrays of Ints
var arr = [[Int]]()
或者:
// 2 dimensional array of arrays of Ints
var arr: [[Int]] = []
或者,如果您需要一個預定義大小的數組(如評論中 @0x7fffffff 所述):
// 2 dimensional array of arrays of Ints set to 0. Arrays size is 10x5
var arr = Array(count: 3, repeatedValue: Array(count: 2, repeatedValue: 0))
// ...and for Swift 3+:
var arr = Array(repeating: Array(repeating: 0, count: 2), count: 3)
arr[0][1] = 18
或者
let myVar = 18
arr[0][1] = myVar
arr[1] = [123, 456, 789]
或者
arr[0] += 234
或者
arr[0] += [345, 678]
如果在這些更改之前您有 0(零)的 3x2 數組,那么現在您有:
[
[0, 0, 234, 345, 678], // 5 elements!
[123, 456, 789],
[0, 0]
]
因此請注意,子數組是可變的,您可以重新定義表示矩陣的初始數組。
let a = 0
let b = 1
if arr.count > a && arr[a].count > b {
println(arr[a][b])
}
備注: 3 維和 N 維數組的標記規則相同。
從文檔:
您可以通過嵌套方括號對來創建多維數組,其中元素的基本類型的名稱包含在最里面的一對方括號中。 例如,您可以使用三組方括號創建一個整數的三維數組:
var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
訪問多維數組中的元素時,最左邊的下標索引指的是最外層數組中該索引處的元素。 右邊的下一個下標索引指的是嵌套在數組中該索引處的元素。依此類推。 這意味着在上面的例子中,array3D[0] 指的是 [[1, 2], [3, 4]],array3D[0][1] 指的是 [3, 4],array3D[0][1 ][1] 指的是值 4。
使其通用Swift 4
struct Matrix<T> {
let rows: Int, columns: Int
var grid: [T]
init(rows: Int, columns: Int,defaultValue: T) {
self.rows = rows
self.columns = columns
grid = Array(repeating: defaultValue, count: rows * columns) as! [T]
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> T {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
var matrix:Matrix<Bool> = Matrix(rows: 1000, columns: 1000,defaultValue:false)
matrix[0,10] = true
print(matrix[0,10])
使用Array(repeating: Array(repeating: {value}, count: 80), count: 24)
時應該小心。
如果值是一個由MyClass()
初始化的對象,那么它們將使用相同的引用。
Array(repeating: Array(repeating: MyClass(), count: 80), count: 24)
不會在每個數組元素中創建MyClass
的新實例。 此方法只創建一次MyClass
並將其放入數組中。
這是一種初始化多維數組的安全方法。
private var matrix: [[MyClass]] = MyClass.newMatrix()
private static func newMatrix() -> [[MyClass]] {
var matrix: [[MyClass]] = []
for i in 0...23 {
matrix.append( [] )
for _ in 0...79 {
matrix[i].append( MyClass() )
}
}
return matrix
}
在斯威夫特 4
var arr = Array(repeating: Array(repeating: 0, count: 2), count: 3)
// [[0, 0], [0, 0], [0, 0]]
根據 swift 4.1 的 Apple 文檔,您可以輕松地使用此結構來創建 2D 數組:
鏈接: https ://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Subscripts.html
代碼示例:
struct Matrix {
let rows: Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(repeating: 0.0, count: rows * columns)
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
在 Swift 中使用多維數組之前,請考慮它們對性能的影響。 在我的測試中,扁平陣列的性能幾乎是 2D 版本的 2 倍:
var table = [Int](repeating: 0, count: size * size)
let array = [Int](1...size)
for row in 0..<size {
for column in 0..<size {
let val = array[row] * array[column]
// assign
table[row * size + column] = val
}
}
填充 50x50 數組的平均執行時間:82.9ms
對比
var table = [[Int]](repeating: [Int](repeating: 0, count: size), count: size)
let array = [Int](1...size)
for row in 0..<size {
for column in 0..<size {
// assign
table[row][column] = val
}
}
填充 50x50 2D 數組的平均執行時間:135ms
兩種算法都是 O(n^2),所以執行時間的差異是由我們初始化表的方式造成的。
最后,你能做的最糟糕的事情是使用append()
添加新元素。 在我的測試中,這被證明是最慢的:
var table = [Int]()
let array = [Int](1...size)
for row in 0..<size {
for column in 0..<size {
table.append(val)
}
}
使用 append() 填充 50x50 數組的平均執行時間:2.59 秒
如果執行速度很重要,請避免使用多維數組並使用索引訪問。 一維數組的性能更高,但您的代碼可能更難理解。
從我的 GitHub 存儲庫下載演示項目后,您可以自己運行性能測試: https ://github.com/nyisztor/swift-algorithms/tree/master/big-o-src/Big-O.playground
這可以在一個簡單的行中完成。
斯威夫特 5
var my2DArray = (0..<4).map { _ in Array(0..<) }
您還可以將其映射到您選擇的任何類或結構的實例
struct MyStructCouldBeAClass {
var x: Int
var y: Int
}
var my2DArray: [[MyStructCouldBeAClass]] = (0..<2).map { x in
Array(0..<2).map { MyStructCouldBeAClass(x: x, y: $0)}
}
斯威夫特 5.5 版
這個版本使用一個底層的可選數組來避免由使用斷言引起的運行時意外。
struct Matrix<T> {
let numberOfRows: Int
let numberOfColumns: Int
var elements: [T?]
/// Creates a new matrix whose size is defined by the specified number of rows and columns.
/// containing a single, repeated optional value.
///
/// - Parameters:
/// - repeatedValue: The element to repeat
/// - numberOfRows: The number of rows
/// - numberOfColumns: The number of columns
init(repeating repeatedValue: T? = nil, numberOfRows: Int, numberOfColumns: Int) {
// counts must be zero or greater.
let numberOfRows = numberOfRows > 0 ? numberOfRows : 0
let numberOfColumns = numberOfColumns > 0 ? numberOfColumns : 0
self.numberOfRows = numberOfRows
self.numberOfColumns = numberOfColumns
self.elements = Array(repeating: repeatedValue, count: numberOfRows * numberOfColumns)
}
subscript(row: Int, column: Int) -> T? {
get { elements[(row * numberOfColumns) + column] }
set { elements[(row * numberOfColumns) + column] = newValue }
}
}
我會使用一維數組並單獨索引它。 例如考慮使用:
struct MatrixIndexer {
var rows: Int
var columns: Int
var count: Int {
return rows * columns
}
subscript(_ r: Int, _ c: Int) -> Int {
precondition(r < rows && c < columns)
return r * columns + c
}
func coordinate(_ i: Int) -> (row: Int, column: Int) {
precondition(i < count)
return (i / columns, i % columns)
}
}
let at = MatrixIndexer(rows: 16, columns: 8)
var array2D: [Float] = Array(repeating: 0, count: at.count)
array2D[at[3, 4]] = 3
array2D[at[5, 2]] = 6
(如果你想傳遞一個單一的結構,你可以引入一個包含Array2D
和一個Array
的MatrixIndexer
)。
為什么這是個好主意? 首先,您可以獲得更好的開箱即用操作,例如:
其次,它的性能也好得多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.