Search code examples
iosxcodetreeswift3dynamic-arrays

Create multidimentional array in swift with different datatypes


this is my first question here so forgive me if it is not very clear.

I am trying to create an array in swift that will store either arrays of arrays or an integer number. The array is supposed to be a simple representation of the data I will be using which is basically a tree kind of data structure like so...

Array = [ [[ [2, 3] ], [ 1, 4 ], [ 2 ]], [ 2 ], [[2, 5], [6, 1] ], 3 ]

In overall the arrays are the branches and the integers are the leaves

I've tried declaring them as optionals like so

var test2 = [[[Int]?]?]()

Or using typedef's but I still can't get it to work.

Also, it should be possible to add new leaves to any of the arrays


Solution

  • Here is a solution based on enum, first declare the enum:

    enum Node
    {
        case leaf(Int)
        case branch([Node])
    }
    

    You can now write things such as:

    let x = Node.leaf(42)
    let y = Node.branch([Node.leaf(42), Node.leaf(24)])
    

    However this is going to become laborious very quickly. Fortunately Swift allows conversions from literals, so we add:

    extension Node : ExpressibleByIntegerLiteral
    {
        init(integerLiteral value: Int)
        {
            self = .leaf(value)
        }
    }
    
    extension Node : ExpressibleByArrayLiteral
    {
        init(arrayLiteral elements: Node...)
        {
            self = .branch(elements)
        }
    }
    

    And with those added we can now write the above two let statements as:

    let x : Node = 42
    let y : Node = [42, 24]
    

    which is nicer. However if we print(y) we get:

    branch([Node.leaf(42), Node.leaf(24)])
    

    If you wish to pretty print that you can add:

    extension Node : CustomStringConvertible
    {
        var description : String
        {
            switch self
            {
                case .leaf(let value):
                        return value.description
                case .branch(let branches):
                        return branches.description
            }
        }
    }
    

    And now print(y) gives you:

    [42, 24]
    

    Finally your example:

    let w : Node = [[[[2, 3]], [1, 4], [2]], [2], [[2, 5], [6, 1]], 3]
    

    which prints as:

    [[[[2, 3]], [1, 4], [2]], [2], [[2, 5], [6, 1]], 3]
    

    You'll want to complete the enum type, with predicates such as isLeaf etc., but that is the basic idea.

    HTH