在我们进行两个字典的合并时,可以使用官方 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 编码带来的快感😏。