2 Dimensional Array

I have the following class

class Matches {

var name : String?
var handicap : Int?
var displayName : String?

init(name: String, handicap: Int, displayName: String) {

    self.name = name
    self.handicap = handicap
    self.displayName = displayName
}

}

I have declared a 2 dimensional array

var matches = [[Matches]]

Declared the following
var data = Matches(name: "simon", handicap: 2, displayName: "FD")

and then wanted to add the data to the array

matches[0].append(data)

This gets an index out of range. I can create an entry with the following

matches.append([data])

then
matches[0].append(data) works. But cannot see how to add a different dimension to the array.

Any help welcome.

This isn't a 2-dimensional array. It's an array of arrays. Any previous experience you've had with pseudo-2-dimensional arrays in (for example) C doesn't apply here.

You could define your own type that allows 2 subscripts (so you'd be able to write accesses like array[i, j], but you'd have to come up with your own implementation that figures out how to store the elements. You could even provide an implementation like C's, where you require all the array dimensions except one to be constant, then actually store the elements in a single-dimension Array. Or, you could provide the storage as an array of arrays, but you'd need to monitor the number of elements in each sub-array.

You'd also have to decide on the semantics of operations like "append". Which dimensions can be appended to?

Deciding between these various alternatives and options is going to depend on a clearer statement of what you need to do with these "2 dimensional" arrays.

1 Like

If you're okay with an Array-Of-Arrays, what you could do is write an extension to handle the complications when there isn't an array at the index you're wanting to append:

()

extension Array {
    /// This is the quick and easy version, if this is production code it should be more robust
    mutating func append<T>(_ element: T, toIndex index: Index) where Element == Array<T> {
        if index >= count {
            // Adds empty arrays when
            (0...(index - count)).forEach { _ in
                append(Array<T>())
            }
        }
        self[index].append(element)
    }
}

var matches: [[Matches]] = []
let newMatches = Matches(name: "simon", handicap: 2, displayName: "FD")
matches.append(newMatches, toIndex: 0)

print(matches[0][0].name) // prints Optional("simon")

Thanks, you are right I mean an array of arrays. I m managed to fix it by using

if row == 0 {
matches.append([data])
} else {
matches[section].append(data)
}

Thanks for your help.

This doesn't really fix your issue. And if it does, it is very fragile and can easily lead to bugs.
If you call this function in any other order, it will fail. If row != 0 and matches contains data, and you append the new row, it'll end up at the end of your outer array, and not at the zeroth position.

If you populate your array inside a for-loop, you should change it to a map instead. And if you populate your array imperatively from some function, you should create some kind of two-dimensional data structure that stores sparsely populated data using a custom subscript, methinks.