我的问题很简单,我想知道如何对 2 个 Swift 词典(不是 NSDictionary)进行深度合并。
let dict1 = [
"a": 1,
"b": 2,
"c": [
"d": 3
],
"f": 2
]
let dict2 = [
"b": 4,
"c": [
"e": 5
],
"f": ["g": 6]
]
let dict3 = dict1.merge(dict2)
/* Expected:
dict3 = [
"a": 1,
"b": 4,
"c": [
"d": 3,
"e": 5
],
"f": ["g": 6]
]
*/
Run Code Online (Sandbox Code Playgroud)
当dict1和dict2具有相同的键时,我希望该值被替换,但如果该值是另一个字典,我希望它被递归合并。
这是我想要的解决方案:
protocol Mergeable {
mutating func merge(obj: Self)
}
extension Dictionary: Mergeable {
// if they have the same key, the new value is taken
mutating func merge(dictionary: Dictionary) {
for (key, value) in dictionary {
let oldValue = self[key]
if oldValue is Mergeable && value is Mergeable {
var oldValue = oldValue as! Mergeable
let newValue = value as! Mergeable
oldValue.merge(newValue)
self[key] = oldValue
} else {
self[key] = value
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但它给了我错误 Protocol 'Mergeable' can only be used as a generic constraint because it has Self or associated type requirements
编辑: 我的问题与Swift不同:如何组合两个 Dictionary 实例?因为那不是深度合并。
使用该解决方案,它将产生:
dict3 = [
"a": 1,
"b": 4,
"c": [
"e": 5
]
]
Run Code Online (Sandbox Code Playgroud)
在我看来,这个问题是不连贯的。然而,这是一个答案:
func deepMerge(d1:[String:AnyObject], _ d2:[String:AnyObject]) -> [String:AnyObject] {
var result = [String:AnyObject]()
for (k1,v1) in d1 {
result[k1] = v1
}
for (k2,v2) in d2 {
if v2 is [String:AnyObject], let v1 = result[k2] where v1 is [String:AnyObject] {
result[k2] = deepMerge(v1 as! [String:AnyObject],v2 as! [String:AnyObject])
} else {
result[k2] = v2
}
}
return result
}
Run Code Online (Sandbox Code Playgroud)
这是您的测试用例:
let dict1:[String:AnyObject] = [
"a": 1,
"b": 2,
"c": [
"d": 3
]
]
let dict2:[String:AnyObject] = [
"b": 4,
"c": [
"e": 5
]
]
let result = deepMerge(dict1, dict2)
NSLog("%@", result)
/*
{
a = 1;
b = 4;
c = {
d = 3;
e = 5;
};
}
*/
Run Code Online (Sandbox Code Playgroud)
第 3 方编辑:使用变量绑定和更新的 Swift 语法的替代版本。
func deepMerge(_ d1: [String: Any], _ d2: [String: Any]) -> [String: Any] {
var result = d1
for (k2, v2) in d2 {
if let v1 = result[k2] as? [String: Any], let v2 = v2 as? [String: Any] {
result[k2] = deepMerge(v1, v2)
} else {
result[k2] = v2
}
}
return result
}
Run Code Online (Sandbox Code Playgroud)
手动做怎么样。
func += <KeyType, ValueType> (inout left: Dictionary<KeyType, ValueType>, right: Dictionary<KeyType, ValueType>) {
for (k, v) in right {
left.updateValue(v, forKey: k)
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以尝试ExSwift 库
| 归档时间: |
|
| 查看次数: |
1176 次 |
| 最近记录: |