iOSDev solution is good and self-explaining recursive function.
I would add here another way to handle dictionaries in using Swift method merging(_:uniquingKeysWith:)
Creates a dictionary by merging key-value pairs in a sequence into the dictionary, using a combining closure to determine the value for duplicate keys.
It is available in Swift since version 4.2
Your solution may look natively
func mergeStandard(_ one: [String: [String: [String: String]]],
_ two: [String: [String: [String: String]]]) -> [String: [String: [String: String]]] {
return one.merging(two) {
$0.merging($1) {
$0.merging($1) { value1, value2 -> String in
return value1 // which is logically wrong, as we should have both values, see the Further Steps section
}
}
}
}
let a = ["Abc": ["Def": ["Jkl": "xxx"]]]
let b = ["Abc": ["Ghi": ["Mno": "yyy"]]]
let c = ["Abc": ["Ghi": ["Pqr": "zzz"]]]
let d = mergeStandard(a, b)
let e = mergeStandard(d, c)
print(e)
//["Abc": ["Def": ["Jkl": "xxx"], "Ghi": ["Mno": "yyy", "Pqr": "zzz"]]]
N.B.!
when you try some different input, like
let a = ["Abc": ["Def": ["Jkl": "xxx"]]]
let b = ["Abc": ["Ghi": ["Mno": "yyy", "Pqr": "qqq"]]]
let c = ["Abc": ["Ghi": ["Pqr": "zzz"]]]
Because you have two "Pqr"
keys. The code above will select the value "qqq"
for the key "Pqr"
. The another answer - from iOSDev has the same issue. Please, see the solution for this case below.
Further Steps
I would recommend you to change your data structure to [String: [String: [String: [String]]]]
, so you will have the last value as Sequence
of String
.
And then you could use the following:
func mergeUpgraded(_ one: [String: [String: [String: [String]]]],
_ two: [String: [String: [String: [String]]]]) -> [String: [String: [String: [String]]]] {
return one.merging(two) {
$0.merging($1) {
$0.merging($1) { (arr1, arr2) -> [String] in
var a = arr1
var b = arr2
a.append(contentsOf: b)
return a
}
}
}
}
let a = ["Abc": ["Def": ["Jkl": ["xxx"]]]]
let b = ["Abc": ["Ghi": ["Mno": "yyy", "Pqr": "qqq"]]]
let c = ["Abc": ["Ghi": ["Pqr": "zzz"]]]
let d = mergeUpgraded(a, b)
let e = mergeUpgraded(d, c)
print(e)
// ["Abc": ["Ghi": ["Mno": ["yyy"], "Pqr": ["qqq", "zzz"]], "Def": ["Jkl": ["xxx"]]]]