简体   繁体   中英

Convert array to dictionary in Swift

I am having trouble coming up with an algorithm to convert an array into a dictionary. The array has the following structure:

let array = [
    Parameter(type: "string", name: "name1", value: "bar", parent: nil),
    Parameter(type: "bool", name: "name2", value: true, parent: nil),
    Parameter(type: "array", name: "name3", value: [], parent: nil),
    Parameter(type: "bool", name: "name3.1", value: false, parent: "name3"),
    Parameter(type: "array", name: "name3.2", value: [], parent: "name3"),
    Parameter(type: "string", name: "name4.1", value: "baz", parent: "name3.2")
]

Parameter is a simple struct. Output should be a dictionary. In the example given above this should look something like this:

[
    "name1": "bar",
    "name2": true,
    "name3": [
        "name3.1": false,
        "name3.2": [
            "name4.1": "baz"
        ]
    ]
]

In the case a given struct does not have a parent it is pretty basic to implement but I am having trouble implementing the other case:

func makeDictionary(from array: [Parameter]) -> [String: Any] {
    var dictionary: [String: Any] = [:]
    for parameter in array {
        if let parent = parameter.parent {
            #warning("how to handle this case?")
        } else {
            dictionary[parameter.name] = parameter.value
        }
    }
    return dictionary
}

Since the array could be unordered how would I handle the case receiving the "name4.1" parameter before the array "name3.2" or the array "name3" is created and available in my dictionary?

To solve this we need to use recursion to connect parent objects with child objects. Here is a solution with one normal function that iterates over the top-level parents (that is objects without a parent) and then call a recursive function for any parent of type "array", that is a parent that might have children.

//Main function
func makeDictionary(from array: [Parameter]) -> [String: Any] {
    let parents = array.filter { $0.parent == nil }
    var dictionary = [String: Any]()

    for parent in parents {
        if parent.type == "array" {
            let child = allChildren(for: array.filter { $0.parent == parent.name }, in: array)
            dictionary[parent.name] = child
        } else {
            dictionary[parent.name] = parent.value
        }
    }
    return dictionary
}

//Recursive function
func allChildren(for children: [Parameter], in array: [Parameter]) -> [[String: Any]] {
    var result = [[String: Any]]()

    for child in children {
        if child.type == "array" {
            let children = allChildren(for: array.filter { $0.parent == child.name }, in: array)
            result.append([child.name: children])
        } else {
            result.append([child.name: child.value])
        }
    }
    return result
}

Example

let dictionary = makeDictionary(from: array)
print(dictionary)

["name3": [["name3.1": false], ["name3.2": [["name4.1": "baz"]]]], "name2": true, "name1": "bar"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM