1

I want to create a function that takes in a one-dimensional array of numbers and a shape, and returns an array that contains those numbers that has the shape given. For instance if I give it the array [1, 2, 3, 4] and the shape [2, 2] I want it to give me the two dimensional array [[1, 2], [3, 4]].

I know this is pretty simple, but my problem is specifying a return type. I would like to avoid just using the [Any] return type for the function. Like if the given shape is two-dimensional, the return type should be [[Int]], 3 dimensional [[[Int]]], etc. How would I specify an integer array with an arbitrary number of dimensions as the return type? Is this even possible?

I'm pretty new to swift so I don't fully understand the whole philosophy of it yet. Thanks!

0

1 Answer 1

1

What you're describing is a matrix. That's not the same thing as an array of arrays. For example, the following is a legal [[Int]], but is an illegal Matrix2:

[[1, 2], [1]]

Swift doesn't have a built-in matrix type. You have to build your own. There are a lot of small projects out there to look for inspiration. I don't know if any are really baked enough to consider full implementations, but they're good enough to get you on the right track. They often want to include Accelerate, which greatly increases the complexity if you don't need it.

The heart of any Matrix type, if you want to build your own, is something like this:

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
        }
    }
}

The key point is that storage is just a flat array of elements, and you subscript into it by row and column.

One nice thing about this design is that your question falls out almost trivially, since your input is exactly the storage.

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
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.