swift - 如何深度合并 2 个 Swift 词典

标签 swift dictionary

我的问题很简单,我想知道如何深度合并 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]
]

*/

dict1dict2 具有相同的键时,我希望该值被替换,但如果该值是另一个字典,我希望它被递归合并。

这是我想要的解决方案:

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

}

但它给了我错误Protocol 'Mergeable' can only be used as a generic constraint because it has Self or associated type requirements

编辑: 我的问题不同于 Swift: how to combine two Dictionary instances?因为那不是深度合并。

有了这个解决方案,它会产生:

dict3 = [
    "a": 1,
    "b": 4,
    "c": [
        "e": 5
    ]
]

最佳答案

在我看来,这个问题是不连贯的。然而,这是一个答案:

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
}

这是你的测试用例:

    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;
        };
    }
    */

第 3 方编辑:使用变量绑定(bind)和更新的 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
}

关于swift - 如何深度合并 2 个 Swift 词典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32929981/

相关文章:

ios - 从服务器下载图像后动态制作表格 View 单元格高度

ios - swift 地,父类(super class)的函数如何通过协议(protocol)/委托(delegate)使用子类的函数?

ios - 快速将数据从 IOS 应用程序传输到 Watch 应用程序

python - python中的list(set)操作是O(1)吗?

python - 动态从列表-字典混合列表中获取值

swift - 反转 Swift 字典中值的键,收集重复值

ios - 在 Swift 中模拟具有泛型参数函数的类

swift - 你如何在 UIKit View Controller 和它呈现的 SwiftUI View 之间共享数据模型?

python - 处理 dict 中的 keyerror 的最佳方法

python - 在Python中对字典进行排序