如何将一个项目的词典添加到另一个词典

Swift中的数组支持+ =操作符将一个数组的内容添加到另一个数组中。 是否有一个简单的方法来做到这一点的字典?

例如:

var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var combinedDict = ... (some way of combining dict1 & dict2 without looping) 

你可以为Dictionary定义+=运算符,例如,

 func += <K, V> (left: inout [K:V], right: [K:V]) { for (k, v) in right { left[k] = v } } 

目前,查看“字典的Swift标准库参考 ”,没有办法轻松更新另一个字典。

你可以写一个扩展名来完成

 var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] extension Dictionary { mutating func update(other:Dictionary) { for (key,value) in other { self.updateValue(value, forKey:key) } } } dict1.update(dict2) // dict1 is now ["a" : "foo", "b" : "bar] 

怎么样

 dict2.forEach { (k,v) in dict1[k] = v } 

这增加了所有的dict2的键和值到dict1。

它不是内置到Swift库中,但可以添加运算符重载所需的内容,例如:

 func + <K,V>(left: Dictionary<K,V>, right: Dictionary<K,V>) -> Dictionary<K,V> { var map = Dictionary<K,V>() for (k, v) in left { map[k] = v } for (k, v) in right { map[k] = v } return map } 

这会重载字典的+运算符,您现在可以使用+运算符添加字典,例如:

 var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var dict3 = dict1 + dict2 // ["a": "foo", "b": "bar"] 

Swift 3:

 extension Dictionary { mutating func merge(with dictionary: Dictionary) { dictionary.forEach { updateValue($1, forKey: $0) } } func merged(with dictionary: Dictionary) -> Dictionary { var dict = self dict.merge(with: dictionary) return dict } } let a = ["a":"b"] let b = ["1":"2"] let c = a.merged(with: b) print(c) //["a": "b", "1": "2"] 

Swift 2.0

 extension Dictionary { mutating func unionInPlace(dictionary: Dictionary) { dictionary.forEach { self.updateValue($1, forKey: $0) } } func union(var dictionary: Dictionary) -> Dictionary { dictionary.unionInPlace(self) return dictionary } } 

不可变

我更喜欢将不可变字典与+运算符结合/联合,所以我实现了它:

 // Swift 2 func + <K,V> (left: Dictionary<K,V>, right: Dictionary<K,V>?) -> Dictionary<K,V> { guard let right = right else { return left } return left.reduce(right) { var new = $0 as [K:V] new.updateValue($1.1, forKey: $1.0) return new } } let moreAttributes: [String:AnyObject] = ["Function":"authenticate"] let attributes: [String:AnyObject] = ["File":"Auth.swift"] attributes + moreAttributes + nil //["Function": "authenticate", "File": "Auth.swift"] attributes + moreAttributes //["Function": "authenticate", "File": "Auth.swift"] attributes + nil //["File": "Auth.swift"] 

易变的

 // Swift 2 func += <K,V> (inout left: Dictionary<K,V>, right: Dictionary<K,V>?) { guard let right = right else { return } right.forEach { key, value in left.updateValue(value, forKey: key) } } let moreAttributes: [String:AnyObject] = ["Function":"authenticate"] var attributes: [String:AnyObject] = ["File":"Auth.swift"] attributes += nil //["File": "Auth.swift"] attributes += moreAttributes //["File": "Auth.swift", "Function": "authenticate"] 

使用扩展名的更可读的变体。

 extension Dictionary { func merge(dict: Dictionary<Key,Value>) -> Dictionary<Key,Value> { var mutableCopy = self for (key, value) in dict { // If both dictionaries have a value for same key, the value of the other dictionary is used. mutableCopy[key] = value } return mutableCopy } } 

你也可以使用reduce来合并它们。 在操场上试试这个

 let d1 = ["a":"foo","b":"bar"] let d2 = ["c":"car","d":"door"] let d3 = d1.reduce(d2) { (var d, p) in d[p.0] = p.1 return d } 

你可以试试这个

  var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var temp = NSMutableDictionary(dictionary: dict1); temp .addEntriesFromDictionary(dict2) 

我推荐SwifterSwift库 。 然而,如果你不想使用整个库和所有的伟大的补充,你可以利用他们的字典的扩展:

Swift 3+

 public extension Dictionary { public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) { rhs.forEach({ lhs[$0] = $1}) } } 

就像@ farhadf的答案一样,但是被Swift 3采用:

 let sourceDict1 = [1: "one", 2: "two"] let sourceDict2 = [3: "three", 4: "four"] let result = sourceDict1.reduce(sourceDict2) { (partialResult , pair) in var partialResult = partialResult //without this line we could not modify the dictionary partialResult[pair.0] = pair.1 return partialResult } 

您可以迭代要合并的值的键值组合,并通过updateValue(forKey :)方法添加它们:

 dictionaryTwo.forEach { dictionaryOne.updateValue($1, forKey: $0) } 

现在dictionaryTwo的所有值都被添加到了dictionaryOne中。

现在不需要任何字典扩展。 Swift(Xcode 9.0+)字典已经得到了这个function。 看看这里 。 下面是一个关于如何使用它的例子

  var oldDictionary = ["a": 1, "b": 2] var newDictionary = ["a": 10000, "b": 10000, "c": 4] oldDictionary.merge(newDictionary) { (oldValue, newValue) -> Int in // This closure return what value to consider if repeated keys are found return newValue } print(oldDictionary) // Prints ["b": 10000, "a": 10000, "c": 4] 

ExSwift库提供了字典合并(称为Union,定义为pipe道运算符'|'),以及基本types的许多其他便利function。

你可以像这样添加一个Dictionary扩展

 extension Dictionary { func mergedWith(otherDictionary: [Key: Value]) -> [Key: Value] { var mergedDict: [Key: Value] = [:] [self, otherDictionary].forEach { dict in for (key, value) in dict { mergedDict[key] = value } } return mergedDict } } 

然后用法如下简单

 var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var combinedDict = dict1.mergedWith(dict2) // => ["a": "foo", "b": "bar"] 

如果你更喜欢一个框架,也包括一些更方便的function,然后检查HandySwift 。 只要将它导入到您的项目中 ,您就可以使用上面的代码, 而无需自行添加任何扩展

Swift 3,词典扩展:

 public extension Dictionary { public static func +=(lhs: inout Dictionary, rhs: Dictionary) { for (k, v) in rhs { lhs[k] = v } } } 

您可以使用bridgeToObjectiveC()函数使字典成为NSDictionary。

将如下所示:

 var dict1 = ["a":"Foo"] var dict2 = ["b":"Boo"] var combinedDict = dict1.bridgeToObjectiveC() var mutiDict1 : NSMutableDictionary! = combinedDict.mutableCopy() as NSMutableDictionary var combineDict2 = dict2.bridgeToObjectiveC() var combine = mutiDict1.addEntriesFromDictionary(combineDict2) 

然后你可以转换NSDictionary(结合)回去或做任何事情。

 import Foundation let x = ["a":1] let y = ["b":2] let out = NSMutableDictionary(dictionary: x) out.addEntriesFromDictionary(y) 

结果是NSMutableDictionary不是Swifttypes的字典,但是使用它的语法是相同的(在这种情况下, out["a"] == 1 ),所以如果你使用第三方需要Swift字典的代码,或者真的需要types检查。

这里的简短答案是,你实际上必须循环。 即使你没有明确地input它,这就是你调用的方法(addEntriesFromDictionary:这里)。 我build议如果你有点不清楚为什么会这样,你应该考虑如何合并两棵B树的叶节点。

如果你确实需要一个Swift本地字典types作为回报,我会build议:

 let x = ["a":1] let y = ["b":2] var out = x for (k, v) in y { out[k] = v } 

这种方法的缺点是字典索引 – 不pipe它是否完成 – 可能会在循环中重build几次,所以实际上这比字典索引慢了10倍。

所有这些反应都很复杂。 这是我对swift 2.2的解决scheme:

  //get first dictionnary let finalDictionnary : NSMutableDictionary = self.getBasicDict() //cast second dictionnary as [NSObject : AnyObject] let secondDictionnary : [NSObject : AnyObject] = self.getOtherDict() as [NSObject : AnyObject] //merge dictionnary into the first one finalDictionnary.addEntriesFromDictionary(secondDictionnary) 

我只是使用美元库。

https://github.com/ankurp/Dollar/#merge—merge-1

将所有字典合并在一起,后一个字典覆盖给定键的值

 let dict: Dictionary<String, Int> = ["Dog": 1, "Cat": 2] let dict2: Dictionary<String, Int> = ["Cow": 3] let dict3: Dictionary<String, Int> = ["Sheep": 4] $.merge(dict, dict2, dict3) => ["Dog": 1, "Cat": 2, "Cow": 3, "Sheep": 4] 

我的需求是不同的,我需要合并不完整的嵌套数据集,而不会破坏。

 merging: ["b": [1, 2], "s": Set([5, 6]), "a": 1, "d": ["x": 2]] with ["b": [3, 4], "s": Set([6, 7]), "a": 2, "d": ["y": 4]] yields: ["b": [1, 2, 3, 4], "s": Set([5, 6, 7]), "a": 2, "d": ["y": 4, "x": 2]] 

这比我想要的要难。 挑战在于从dynamictypes到静态types的映射,我使用协议来解决这个问题。

另外值得注意的是,当你使用字典字面语法时,你实际上得到了基础types,它们没有select协议扩展。 我放弃了我的努力来支持这些,因为我找不到一个容易validation收集元素的统一性的方法。

 import UIKit private protocol Mergable { func mergeWithSame<T>(right: T) -> T? } public extension Dictionary { /** Merge Dictionaries - Parameter left: Dictionary to update - Parameter right: Source dictionary with values to be merged - Returns: Merged dictionay */ func merge(right:Dictionary) -> Dictionary { var merged = self for (k, rv) in right { // case of existing left value if let lv = self[k] { if let lv = lv as? Mergable where lv.dynamicType == rv.dynamicType { let m = lv.mergeWithSame(rv) merged[k] = m } else if lv is Mergable { assert(false, "Expected common type for matching keys!") } else if !(lv is Mergable), let _ = lv as? NSArray { assert(false, "Dictionary literals use incompatible Foundation Types") } else if !(lv is Mergable), let _ = lv as? NSDictionary { assert(false, "Dictionary literals use incompatible Foundation Types") } else { merged[k] = rv } } // case of no existing value else { merged[k] = rv } } return merged } } extension Array: Mergable { func mergeWithSame<T>(right: T) -> T? { if let right = right as? Array { return (self + right) as? T } assert(false) return nil } } extension Dictionary: Mergable { func mergeWithSame<T>(right: T) -> T? { if let right = right as? Dictionary { return self.merge(right) as? T } assert(false) return nil } } extension Set: Mergable { func mergeWithSame<T>(right: T) -> T? { if let right = right as? Set { return self.union(right) as? T } assert(false) return nil } } var dsa12 = Dictionary<String, Any>() dsa12["a"] = 1 dsa12["b"] = [1, 2] dsa12["s"] = Set([5, 6]) dsa12["d"] = ["c":5, "x": 2] var dsa34 = Dictionary<String, Any>() dsa34["a"] = 2 dsa34["b"] = [3, 4] dsa34["s"] = Set([6, 7]) dsa34["d"] = ["c":-5, "y": 4] //let dsa2 = ["a": 1, "b":a34] let mdsa3 = dsa12.merge(dsa34) print("merging:\n\t\(dsa12)\nwith\n\t\(dsa34) \nyields: \n\t\(mdsa3)") 

Swift 2.2

 func + <K,V>(left: [K : V], right: [K : V]) -> [K : V] { var result = [K:V]() for (key,value) in left { result[key] = value } for (key,value) in right { result[key] = value } return result }