簡體   English   中英

如何創建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]

Xcode 8 Beta 2 Playground中的Swift 3

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擴展Optional (將為nil ),但是您可以為NilLiteralConvertible s創建一個自定義下標, 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的整個目的是不代表任何價值。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM