Swift中的数组支持+ =运算符,将一个数组的内容添加到另一个数组。对于字典有没有简单的方法呢?
例如:
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var combinedDict = ... (some way of combining dict1 & dict2 without looping)
答案 0 :(得分:165)
您可以为+=
定义Dictionary
运算符,例如
func += <K, V> (left: inout [K:V], right: [K:V]) {
for (k, v) in right {
left[k] = v
}
}
答案 1 :(得分:86)
怎么样
dict2.forEach { (k,v) in dict1[k] = v }
将dict2的所有键和值添加到dict1中。
答案 2 :(得分:77)
在Swift 4中,应该使用merging(_:uniquingKeysWith:)
:
using (var client = new WebClient())
{
var values = new NameValueCollection
{
["From"] = _twilioFromPhone,
["To"] = phoneNumber,
["Body"] = body
};
var encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(_accountSid + ":" + _authToken));
client.Headers.Add("Authorization", "Basic " + encoded);
client.Proxy = new WebProxy("[proxy address, not http in front]", proxy port number);
var url = string.Format("https://api.twilio.com/2010-04-01/Accounts/{0}/Messages", _accountSid);
var response = client.UploadValues(url, values);
var responseString = Encoding.Default.GetString(response);
}
答案 3 :(得分:75)
目前,查看词典的Swift Standard Library Reference,无法轻松地用另一个词典更新词典。
你可以写一个扩展来做到这一点
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]
答案 4 :(得分:53)
Swift 4 提供merging(_:uniquingKeysWith:)
,因此对于您的情况:
let combinedDict = dict1.merging(dict2) { $1 }
速记闭包返回$1
,因此当与键冲突时将使用dict2的值。
答案 5 :(得分:31)
它没有内置到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"]
答案 6 :(得分:27)
斯威夫特3:
select cast(getdate() as time(0))
答案 7 :(得分:16)
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
}
}
答案 8 :(得分:12)
我更喜欢将不可变词典与+
运算符结合使用,因此我将其实现为:
// 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"]
答案 9 :(得分:12)
现在无需任何字典扩展。 Swift(Xcode 9.0+)字典有一个功能。看看here。下面是一个如何使用它的例子
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]
答案 10 :(得分:11)
使用扩展程序的更易读的变体。
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
}
}
答案 11 :(得分:11)
你可以试试这个
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var temp = NSMutableDictionary(dictionary: dict1);
temp.addEntriesFromDictionary(dict2)
答案 12 :(得分:10)
您还可以使用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
}
答案 13 :(得分:7)
我推荐SwifterSwift Library。但是,如果您不想使用整个库及其所有附加功能,您只需使用它们的扩展词:
public extension Dictionary {
public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) {
rhs.forEach({ lhs[$0] = $1})
}
}
答案 14 :(得分:6)
您可以迭代要合并的值的键值组合,并通过updateValue(forKey :)方法添加它们:
dictionaryTwo.forEach {
dictionaryOne.updateValue($1, forKey: $0)
}
现在,dictionaryTwo的所有值都被添加到dictionaryOne。
答案 15 :(得分:5)
与@ 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
}
答案 16 :(得分:3)
您可以像这样添加 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"]
如果您更喜欢的框架还包含一些更便利的功能,请结帐 HandySwift 。只需将其导入您的项目,您就可以使用上述代码而无需向项目添加任何扩展程序。
答案 17 :(得分:3)
Swift 3,字典扩展名:
public extension Dictionary {
public static func +=(lhs: inout Dictionary, rhs: Dictionary) {
for (k, v) in rhs {
lhs[k] = v
}
}
}
答案 18 :(得分:2)
不再需要扩展或任何其他功能。 您可以这样写:
firstDictionary.merge(secondDictionary) { (value1, value2) -> AnyObject in
return object2 // what you want to return if keys same.
}
答案 19 :(得分:2)
Swift 4的一些更简化的重载:
extension Dictionary {
static func += (lhs: inout [Key:Value], rhs: [Key:Value]) {
lhs.merge(rhs){$1}
}
static func + (lhs: [Key:Value], rhs: [Key:Value]) -> [Key:Value] {
return lhs.merging(rhs){$1}
}
}
答案 20 :(得分:1)
我只想使用 Dollar 库。
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]
答案 21 :(得分:1)
您可以使用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(组合)或做任何事情。
答案 22 :(得分:1)
import Foundation
let x = ["a":1]
let y = ["b":2]
let out = NSMutableDictionary(dictionary: x)
out.addEntriesFromDictionary(y)
结果是NSMutableDictionary不是Swift类型字典,但使用它的语法是相同的(在这种情况下为out["a"] == 1
)所以如果你使用它只会有问题需要Swift字典的第三方代码,或者真的需要进行类型检查。
这里简短的回答是你实际上必须循环。即使您没有明确输入它,您所调用的方法(addEntriesFromDictionary:here)也会这样做。我建议如果您不清楚为什么会出现这种情况,您应该考虑如何合并两个B树的叶节点。
如果您真的需要一个Swift原生字典类型作为回报,我建议:
let x = ["a":1]
let y = ["b":2]
var out = x
for (k, v) in y {
out[k] = v
}
这种方法的缺点是字典索引 - 无论它已经完成 - 可以在循环中重建几次,所以实际上这比NSMutableDictionary方法慢大约10倍。
答案 23 :(得分:1)
所有这些反应都很复杂。这是我对swift 2.2的解决方案:
//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)
答案 24 :(得分:0)
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
}
答案 25 :(得分:0)
这是我写的一个不错的扩展名...
extension Dictionary where Value: Any {
public func mergeOnto(target: [Key: Value]?) -> [Key: Value] {
guard let target = target else { return self }
return self.merging(target) { current, _ in current }
}
}
使用:
var dict1 = ["cat": 5, "dog": 6]
var dict2 = ["dog": 9, "rodent": 10]
dict1 = dict1.mergeOnto(target: dict2)
然后,将dict1修改为
["cat": 5, "dog": 6, "rodent": 10]
答案 26 :(得分:0)
我的需求不同,我需要合并不完整的嵌套数据集而不会破坏。
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)")
答案 27 :(得分:0)
您可以使用
func addAll(from: [String: Any], into: [String: Any]){
from.forEach {into[$0] = $1}
}