Swift: как объявить 2d-массив (сетку или матрицу) в Swift, чтобы разрешить случайную вставку
Мне нужно иметь возможность хранить информацию о ячейках в 2d-матрице или сетке. Данные не являются непрерывными, поэтому мне может потребоваться хранить данные в 5,5, когда нет данных в нижних строках и столбцах.
моей первой мыслью был массив массивов динамического размера. Но SWIFT массивы имеют границы, которые не растут автоматически. Если я попытаюсь разместить что-то в индексе 5, и это выходит за его текущий размер, он терпит неудачу с исключением границ.
есть ли класс коллекции в Swift или Cocoa, который поддерживает случайный доступ к сетке. NSArray тоже не поддерживает его.
другой мыслью было сохранить элементы в словаре и использовать кортеж строки, столбца в качестве ключа. Однако кортежи не хэшируются и не могут использоваться в качестве ключа к словарю.
мой текущий подход заключается в предварительной инициализации массива с заданным размером, заполненным нулями. Есть ли лучший способ?
1 ответов
вот очень простая реализация, используя Dictionary
в качестве хранилища:
struct Matrix2D<KeyElem:Hashable, Value> {
var _storage:[KeyElem:[KeyElem:Value]] = [:]
subscript(x:KeyElem, y:KeyElem) -> Value? {
get {
return _storage[x]?[y]
}
set(val) {
if _storage[x] == nil {
_storage[x] = [:]
}
_storage[x]![y] = val
}
}
}
var matrix = Matrix2D<Int, String>()
matrix[1,2] = "foo"
as DictionaryLiteralConvertible
:
extension Matrix2D:DictionaryLiteralConvertible {
typealias Key = (x:KeyElem, y:KeyElem)
init(dictionaryLiteral elements: (Key, Value)...) {
for (key, val) in elements {
self[key.x, key.y] = val
}
}
}
var matrix:Matrix2D = [(1,2):"foo", (2,3):"bar"]
Array
серверная версия
struct Matrix2D<T> {
var _storage:[[T?]] = []
subscript(x:Int, y:Int) -> T? {
get {
if _storage.count <= x {
return nil
}
if _storage[x].count <= y {
return nil
}
return _storage[x][y]
}
set(val) {
if _storage.count <= x {
let cols = [[T?]](count: x - _storage.count + 1, repeatedValue: [])
_storage.extend(cols)
}
if _storage[x].count <= y {
let rows = [T?](count: y - _storage[x].count + 1, repeatedValue: nil)
_storage[x].extend(rows)
}
_storage[x][y] = val
}
}
}