What is the syntax for multidimensional array in Swift?

后端 未结 2 1937
慢半拍i
慢半拍i 2021-01-26 13:42

CO fans: before you jump into conclusion it is a duplicate, there are 2 distinct flavours of arrays, and it seems I am asking about less popular one.

So far, I

2条回答
  •  南笙
    南笙 (楼主)
    2021-01-26 14:17

    Yes, there is nothing built-in (as far as I know). You can define a custom class/struct (as in Most efficient way to access multi-dimensional arrays in Swift? or How to Declare a Multidimensional Boolean array in Swift?) with a subscript operator, so that a[0,0] = 1 works.

    Here is a mixture of those solutions, but as a generic struct instead of class. I have also changed the order of the rows and columns parameters because I find that more natural:

    struct Array2D {
        let rows : Int
        let cols : Int
        var matrix: [T]
    
        init(rows : Int, cols : Int) {
            self.rows = rows
            self.cols = cols
            matrix = Array(count : rows * cols, repeatedValue : 0)
        }
    
        subscript(row : Int, col : Int) -> T {
            get { return matrix[cols * row + col] }
            set { matrix[cols*row+col] = newValue }
        }
    }
    

    I don't see how to create such a thing from a literal like [2, 3 ;; -1, 0]. But you could initialize it from a nested array:

    extension Array2D {
    
        init(_ elements: [[T]]) {
            let rows = elements.count
            let cols = elements[0].count
            self.init(rows: rows, cols: cols)
            for i in 0 ..< rows {
                assert(elements[i].count == cols, "Array must have same number of elements for each row")
                self.matrix.replaceRange(cols * i ..< cols * (i+1), with: elements[i])
            }
        }
    }
    

    Example:

    let array = Array2D([[1, 2, 3], [4, 5, 6]])
    println(array.rows)  // 2
    println(array.cols)  // 3
    println(array[1, 2]) // 6
    println(array[1, 0]) // 4
    

    You can additionally implement the ArrayLiteralConvertible protocol to initialize a 2d array from a nested array literal:

    extension Array2D : ArrayLiteralConvertible {
    
        init(arrayLiteral elements: [T]...) {
            self.init(elements)
        }
    }
    

    Example:

    let array : Array2D = [[1, 2, 3], [4, 5, 6]]
    

    For square arrays (rows == columns) you could alternatively initialize it from a plain array:

    extension Array2D {
    
        init(_ elements: [T]) {
            let rows = Int(sqrt(Double(elements.count)))
            assert(rows * rows == elements.count, "Number of array elements must be a square")
            self.init(rows: rows, cols: rows)
            self.matrix = elements
        }
    }
    

    Example:

    let squareArray = Array2D([2, 3, -1, 0])
    println(squareArray.rows)  // 2
    println(squareArray.cols)  // 3
    println(squareArray[1, 0]) // -1
    

提交回复
热议问题