如何在 Swift 中组合两个 Dictionary 实例?

如何使用 Swift 将一个 Dictionary附加到另一个 Dictionary

I am using the AlamoFire library to send JSON content to a 休息 server.

字典1

var dict1: [String: AnyObject] = [
kFacebook: [
kToken: token
]
]

字典2

var dict2: [String: AnyObject] = [
kRequest: [
kTargetUserId: userId
]
]

如何组合这两本字典来编写一本如下所示的新字典?

let parameters: [String: AnyObject] = [
kFacebook: [
kToken: token
],
kRequest: [
kTargetUserId: userId
]
]

我试过 dict1 += dict2,但是我得到了一个编译错误:

二进制运算符“ + =”不能应用于两个“[ String: AnyObject ]”操作数

84127 次浏览
var d1 = ["a": "b"]
var d2 = ["c": "e"]


extension Dictionary {
mutating func merge(dict: [Key: Value]){
for (k, v) in dict {
updateValue(v, forKey: k)
}
}
}


d1.merge(d2)

请参考美元 & 美分项目 Https://github.com/ankurp/cent/blob/master/sources/dictionary.swift

您使用 let 关键字声明字典,因此不能像声明常量那样对字典进行更改。

将其更改为 var 关键字,然后它将为您工作。

var dict1: [String: AnyObject] = [
kFacebook: [
kToken: token
]
]


var dict2: [String: AnyObject] = [
kRequest: [
kTargetUserId: userId
]
]


dict1 += dict2

尝试这种方法

    let dict1: [String: AnyObject] = ["kFacebook": ["kToken": "token"]]
let dict2: [String: AnyObject] = ["kRequest": ["kTargetUserId": "userId"]]


var combinedAttributes : NSMutableDictionary!


combinedAttributes = NSMutableDictionary(dictionary: dict1)


combinedAttributes.addEntriesFromDictionary(dict2)


println(combinedAttributes)

它将印刷如下:

{
kFacebook =     {
kToken = token;
};
kRequest =     {
kTargetUserId = userId;
};

}

希望能有帮助!

SequenceType.forEach(由 Dictionary实现)提供了将字典元素添加到另一个字典的优雅解决方案。

dic1.forEach { dic2[$0] = $1 }

比如说

func testMergeDictionaries() {
let dic1 = [1:"foo"]
var dic2 = [2:"bar"]


dic1.forEach { dic2[$0] = $1 }


XCTAssertEqual(dic2[1], "foo")
}

对于 Swift > = 2.2:
let parameters = dict1.reduce(dict2) { r, e in var r = r; r[e.0] = e.1; return r }

对于 Swift < 2.2:
let parameters = dict1.reduce(dict2) { (var r, e) in r[e.0] = e.1; return r }

Swift 4有一个新功能: let parameters = dict1.reduce(into: dict2) { (r, e) in r[e.0] = e.1 }

深入挖掘标准库非常重要: mapreducedropFirstforEach等都是简洁代码的主要组成部分。功能性的部分很有趣!

extension Dictionary {
static func +=(lhs: inout Self, rhs: Self) {
lhs.merge(rhs) { _ , new in new }
}
static func +=<S: Sequence>(lhs: inout Self, rhs: S) where S.Element == (Key, Value) {
lhs.merge(rhs) { _ , new in new }
}
}

var dic = ["test1": 1]
dic += ["test2": 2]
dic  // ["test1": 1, "test2": 2]
dic += [("test2", 3),("test3", 4)]
dic  // ["test3": 4, "test1": 1, "test2": 3]

我的需求是不同的,我想合并,而不是重击。

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

我本来想找个简单点的解决办法但结果却是这样。挑战在于从动态类型跳到静态类型,我使用协议来解决这个问题。

同样值得注意的是,当您使用字典文字语法时,实际上得到的是基础类型,而不是协议扩展。我放弃了支持这些元素的努力,因为我找不到一个简单的方法来验证集合元素的一致性。

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)")

我喜欢这种方法:

dicFrom.forEach { (key, value) in dicTo[key] = value }

斯威夫特4号和5号

通过 Swift 4,苹果引入了一种更好的合并两本字典的方法:

let dictionary = ["a": 1, "b": 2]
let newKeyValues = ["a": 3, "b": 4]


let keepingCurrent = dictionary.merging(newKeyValues) { (current, _) in current }
// ["b": 2, "a": 1]


let replacingCurrent = dictionary.merging(newKeyValues) { (_, new) in new }
// ["b": 4, "a": 3]

这里有两个选项(与大多数在容器上操作的函数一样) :

  • merge对现有字典进行变异
  • merging返回一个新字典

您可以使用下面的代码在 Swift 中组合两个 dictionary 实例:

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