如何从数据构造一个n维数组

时间:2018-02-24 21:12:56

标签: arrays swift multidimensional-array

我想创建一个函数,它接受一维数字和一个形状的数组,并返回一个包含具有给定形状的数字的数组。例如,如果我给它数组[1,2,3,4]和形状[2,2]我希望它给我二维数组[[1,2],[3,4]]。

我知道这很简单,但我的问题是指定一个返回类型。 我想避免只使用函数的[Any]返回类型。就像给定的形状是二维的一样,返回类型应该是[[Int]],3维[[[Int]]]等。我如何指定一个具有任意维数的整数数组作为返回类型?这甚至可能吗?

我很快乐,所以我还没有完全理解它的整体哲学。谢谢!

1 个答案:

答案 0 :(得分:1)

你所描述的是一个矩阵。这与数组数组不同。例如,以下是合法的[[Int]],但是非法的Matrix2:

[[1, 2], [1]]

Swift没有内置矩阵类型。你必须建立自己的。那里有很多小项目寻找灵感。我不知道是否有足够的东西可以考虑完整实施,但它们足以让你走上正确的轨道。他们通常希望包括Accelerate,如果你不需要它会大大增加复杂性。

任何Matrix类型的核心,如果你想建立自己的类型,都是这样的:

struct Matrix {
    private var storage: [Int]
    let rows: Int
    let columns: Int

    init(rows: Int, columns: Int) {

        precondition(rows > 0 && columns > 0)

        self.rows = rows
        self.columns = columns
        self.storage = Array(repeating: 0, count: rows * columns)
    }

    subscript(row: Int, column: Int) -> Int {
        get {
            return storage[row * columns + column]
        }
        set {
            storage[row * columns + column] = newValue
        }
    }
}

关键是存储只是一个扁平的元素数组,你可以按行和列下标。

这个设计的一个好处是你的问题几乎是微不足道的,因为你的输入正是存储。

extension Matrix {
    enum Error: Swift.Error {
        case invalidShape
    }

    init(rowMajorValues: [Int], rows: Int, columns: Int) throws {
        self.init(rows: rows, columns: columns)
        guard storage.count == rowMajorValues.count else {
            throw Error.invalidShape
        }
        storage = rowMajorValues
    }
}