如何创建 3D NSMutableArray
How to create 3D NSMutableArray
如何创建 Int 的 3D 可变数组?
我希望能够通过说 arr[4][3][5] = 4
插入一个元素,而不必事先确定数组的大小。
var z = [Int](count:10, repeatedValue: 0)
var y = [[Int]](count:10, repeatedValue: z)
var x = [[[Int]]](count:10, repeatedValue: y)
x[A][B][C] = 4
var val = x[2][1][1]
Swift 3 in Xcode 8 beta 2 playground
var z = [Int](repeatElement(0, count: 10))
var y = [[Int]](repeatElement(z, count: 10))
var x = [[[Int]]](repeatElement(y, count: 10))
可能的答案
var z = [0]
var y = [z]
var x = [y]
x[0][0].append(2)
x[0].append([1])
x.append([[3,5],[0]])
print(x)
x[0][0][0] = 2
print(x)
//Output
[[[0, 2], [1]], [[3, 5], [0]]]
[[[2, 2], [1]], [[3, 5], [0]]]
讨论(最终代码见下文)
这里有一个方法:首先我们用一个下标扩展 _ArrayType
,当越界访问一个索引时,它会自动扩展数组。我们将数组给定 fallback
值:
extension _ArrayType {
subscript (extending pos: Int, fallback fallback: Generator.Element) -> Generator.Element {
mutating get {
while count <= pos { append(fallback) }
return self[pos]
}
mutating set {
while count <= pos { append(fallback) }
self[pos] = newValue
}
}
}
可以这样使用:
var a : [Int] = []
a[extending: 3, fallback: 0] = 10
print(a) // [0, 0, 0, 10]
现在我们可以扩展 3 维数组以获得一个方便的自动扩展的下标,如下所示:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType {
typealias T = Generator.Element.Generator.Element.Generator.Element
subscript (x: Int, y: Int, z: Int, `default`: T) -> T {
mutating get {
return self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: `default`]
}
mutating set {
self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: `default`] = newValue
}
}
}
用法:
var array : [[[Int?]]] = []
array[1, 1, 0, nil] = 10
array[2, 0, 1, nil] = 4
print(array) // [[], [[], [Optional(10)]], [[nil, Optional(4)]]]
现在,如果您希望通过预先告知特定类型的默认值应该是什么来更方便,您可以创建一个 HasDefault
协议:
protocol HasDefault {
static var `default` : Self { get }
}
并用它扩展你的类型:
extension Int : HasDefault {
static var `default` = 0
}
extension Bool : HasDefault {
static var `default` = false
}
也做一个不接受最后一个参数的下标:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : HasDefault {
typealias E = Generator.Element.Generator.Element.Generator.Element
subscript (x: Int, y: Int, z: Int) -> E {
mutating get {
return self[x, y, z, E.`default`]
}
mutating set {
self[x, y, z, E.`default`] = newValue
}
}
}
现在可以按照您想要的方式使用它了:
var array : [[[Int]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // 0
print(array) // [[[], [3]], [[], [], [0, 0, 0, 10]], [[0, 0]]]
不幸的是,(目前)还不能用 HasDefault
(即 nil
)扩展 Optional
,但您可以为 NilLiteralConvertible
制作自定义下标Optional
符合:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : NilLiteralConvertible {
subscript (x: Int, y: Int, z: Int) -> Generator.Element.Generator.Element.Generator.Element {
mutating get {
return self[x, y, z, nil]
}
mutating set {
self[x, y, z, nil] = newValue
}
}
}
这样使用:
var array : [[[Int?]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // nil
print(array) // [[[], [3]], [[], [], [nil, nil, nil, 10]], [[nil, nil]]]
我强烈推荐这种方法,因为 Optional
s 的全部目的是不代表任何值。
TL;DR / 最终代码
extension _ArrayType {
subscript (extending pos: Int, fallback fallback: Generator.Element) -> Generator.Element {
mutating get {
while count <= pos { append(fallback) }
return self[pos]
}
mutating set {
while count <= pos { append(fallback) }
self[pos] = newValue
}
}
}
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : NilLiteralConvertible {
subscript (x: Int, y: Int, z: Int) -> Generator.Element.Generator.Element.Generator.Element {
mutating get {
return self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: nil]
}
mutating set {
self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: nil] = newValue
}
}
}
var array : [[[Int?]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // nil
print(array) // [[[], [3]], [[], [], [nil, nil, nil, 10]], [[nil, nil]]]
如何创建 Int 的 3D 可变数组?
我希望能够通过说 arr[4][3][5] = 4
插入一个元素,而不必事先确定数组的大小。
var z = [Int](count:10, repeatedValue: 0)
var y = [[Int]](count:10, repeatedValue: z)
var x = [[[Int]]](count:10, repeatedValue: y)
x[A][B][C] = 4
var val = x[2][1][1]
Swift 3 in Xcode 8 beta 2 playground
var z = [Int](repeatElement(0, count: 10))
var y = [[Int]](repeatElement(z, count: 10))
var x = [[[Int]]](repeatElement(y, count: 10))
可能的答案
var z = [0]
var y = [z]
var x = [y]
x[0][0].append(2)
x[0].append([1])
x.append([[3,5],[0]])
print(x)
x[0][0][0] = 2
print(x)
//Output
[[[0, 2], [1]], [[3, 5], [0]]]
[[[2, 2], [1]], [[3, 5], [0]]]
讨论(最终代码见下文)
这里有一个方法:首先我们用一个下标扩展 _ArrayType
,当越界访问一个索引时,它会自动扩展数组。我们将数组给定 fallback
值:
extension _ArrayType {
subscript (extending pos: Int, fallback fallback: Generator.Element) -> Generator.Element {
mutating get {
while count <= pos { append(fallback) }
return self[pos]
}
mutating set {
while count <= pos { append(fallback) }
self[pos] = newValue
}
}
}
可以这样使用:
var a : [Int] = []
a[extending: 3, fallback: 0] = 10
print(a) // [0, 0, 0, 10]
现在我们可以扩展 3 维数组以获得一个方便的自动扩展的下标,如下所示:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType {
typealias T = Generator.Element.Generator.Element.Generator.Element
subscript (x: Int, y: Int, z: Int, `default`: T) -> T {
mutating get {
return self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: `default`]
}
mutating set {
self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: `default`] = newValue
}
}
}
用法:
var array : [[[Int?]]] = []
array[1, 1, 0, nil] = 10
array[2, 0, 1, nil] = 4
print(array) // [[], [[], [Optional(10)]], [[nil, Optional(4)]]]
现在,如果您希望通过预先告知特定类型的默认值应该是什么来更方便,您可以创建一个 HasDefault
协议:
protocol HasDefault {
static var `default` : Self { get }
}
并用它扩展你的类型:
extension Int : HasDefault {
static var `default` = 0
}
extension Bool : HasDefault {
static var `default` = false
}
也做一个不接受最后一个参数的下标:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : HasDefault {
typealias E = Generator.Element.Generator.Element.Generator.Element
subscript (x: Int, y: Int, z: Int) -> E {
mutating get {
return self[x, y, z, E.`default`]
}
mutating set {
self[x, y, z, E.`default`] = newValue
}
}
}
现在可以按照您想要的方式使用它了:
var array : [[[Int]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // 0
print(array) // [[[], [3]], [[], [], [0, 0, 0, 10]], [[0, 0]]]
不幸的是,(目前)还不能用 HasDefault
(即 nil
)扩展 Optional
,但您可以为 NilLiteralConvertible
制作自定义下标Optional
符合:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : NilLiteralConvertible {
subscript (x: Int, y: Int, z: Int) -> Generator.Element.Generator.Element.Generator.Element {
mutating get {
return self[x, y, z, nil]
}
mutating set {
self[x, y, z, nil] = newValue
}
}
}
这样使用:
var array : [[[Int?]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // nil
print(array) // [[[], [3]], [[], [], [nil, nil, nil, 10]], [[nil, nil]]]
我强烈推荐这种方法,因为 Optional
s 的全部目的是不代表任何值。
TL;DR / 最终代码
extension _ArrayType {
subscript (extending pos: Int, fallback fallback: Generator.Element) -> Generator.Element {
mutating get {
while count <= pos { append(fallback) }
return self[pos]
}
mutating set {
while count <= pos { append(fallback) }
self[pos] = newValue
}
}
}
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : NilLiteralConvertible {
subscript (x: Int, y: Int, z: Int) -> Generator.Element.Generator.Element.Generator.Element {
mutating get {
return self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: nil]
}
mutating set {
self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: nil] = newValue
}
}
}
var array : [[[Int?]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // nil
print(array) // [[[], [3]], [[], [], [nil, nil, nil, 10]], [[nil, nil]]]