如何在 Swift 中合并两个 Dictionary

6,482 阅读2分钟

在我们进行两个字典的合并时,可以使用官方 API:merging(_:uniquingKeysWith:) 进行合并。

合并没有公共键的字典

首先,来看一下如何合并两个没有公共键的字典:

let dict1 = ["name": "Swift", "version": "5.3"]
let dict2 = ["platform": "iOS"]
let total = dict1.merging(dict2) { (first, _) -> String in return first }
print(total) // ["name": "Swift", "version": "5.3", "platform": "iOS"]

通过打印可以看到 total 的键值对是 dict1 和 dict2 的和,大家可能会对 first 这个变量感到疑惑,别急,下面的情况就会讲解它😄。

合并有公共键的字典

接下来,看一下如何合并存在公共键的字典。如果有公共键的话就存在两种情况:使用第一个字典的value;使用第二个字典的 value。那么如何控制呢?这就用到了上面的 first。

使用第一个字典的值


let dict1 = ["name": "Swift", "version": "5.3"]
let dict2 = ["name": "OC"]
let total = dict1.merging(dict2) { (first, _) -> String in return first }
print(total) // ["name": "Swift", "version": "5.3"]

使用第二个字典的值

let dict1 = ["name": "Swift", "version": "5.3"]
let dict2 = ["name": "OC"]
let total = dict1.merging(dict2) { (_, second) -> String in return second }
print(total) // ["name": "OC", "version": "5.3"]

若使用第二个字典的 value,上述代码也可以使用语法糖简化为以下版本:

let total = dict1.merging(dict2) { $1 }

扩展

该函数不仅可以控制使用哪个字典的 value ,我们也可以在闭包中添加相应的逻辑,比如在公共值后面拼接字符串。

let dict1 = ["name": "Swift", "version": "5.3"]
let dict2 = ["name": "OC", "version": "2.0", "platform":"iOS"]
let total = dict1.merging(dict2) { (current, _) in
    return current + " common"
}
print(total) // ["platform": "iOS", "name": "Swift common", "version": "5.3 common"]

知其然,知其所以然

通过上面的例子,相信你已经掌握了它的使用,现在来假设一下它的实现,主要思路有以下两步:

  • 将不共有的key, value 添加到 result
  • 将共有的 key,value 通过 combine 得到的返回值,添加到 result
extension Dictionary {
    func customMergeing(other: Dictionary, combine: (_ v1: Value, _ v2: Value) -> Value) -> [Key: Value] {
        var result = self
        // 找出不同的key,并将相应的 value 添加到 result 中
        let key1 = Set(self.keys)
        let key2 = Set(other.keys)
        let diff = key2.subtracting(key1)
        for key in diff {
            result[key] = other[key]
        }
        // 找出相同的key,并将相应的 value 添加到 result 中
        let common = key1.intersection(key2)
        for key in common {
            result[key] = combine(self[key]!, other[key]!)
        }
        return result
    }
}

上面的代码是我自己实现的合并功能的函数,通过下述代码测得原生函数的性能大概是自定义函数的 30 倍🤣🤣🤣(大家如果有更好的思路,希望在评论区不吝赐教)。以下为测试代码:

let dict1 = ["name": "Swift", "version": "5.3", "a": "b", ]
let dict2 = ["name": "OC", "version": "2.0", "platform":"iOS"]

func test1() {
    let begin = CACurrentMediaTime()
    for _ in 0...num {
        let _ = dict1.merging(dict2) { (current, _) in current + "common" }
    }
    let end = CACurrentMediaTime()
    print(end - begin)
}

func test2() {
    let begin = CACurrentMediaTime()
    for _ in 0...num {
        let _ = dict1.customMergeing(other: dict2) { (current, _) in current + "common" }
    }
    let end = CACurrentMediaTime()
    print(end - begin)
}

test1() // 0.3502225889824331
test2() // 11.097703097155318

希望通过本文能给大家带来一些收获,能更好的享用 Swift 编码带来的快感😏。