Как совместить два экземпляра словаря в Swift?
Как добавить один Dictionary
в другой Dictionary
с помощью Swift
?
Я использую библиотеку AlamoFire
для отправки JSON
на REST 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]'
Ответы
Ответ 1
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)
Обратитесь к удивительному проекту Dollar and Cent
https://github.com/ankurp/Cent/blob/master/Sources/Dictionary.swift
Ответ 2
Мне нравится этот подход:
dicFrom.forEach { (key, value) in dicTo[key] = value }
Свифт 4 и 5
В Swift 4 Apple предлагает лучший подход для объединения двух словарей:
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]
Здесь у вас есть 2 варианта (как и для большинства функций, работающих с контейнерами):
-
merge
мутирует существующий словарь -
merging
возвращает новый словарь
Ответ 3
Для 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 }
Очень важно покопаться в стандартной библиотеке: map
, reduce
, dropFirst
, forEach
и т.д. Являются основными элементами краткого кода. Функциональные биты - это весело!
Ответ 4
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")
}
Ответ 5
func +=<Key, Value> (lhs: inout [Key: Value], rhs: [Key: Value]) {
rhs.forEach{ lhs[$0] = $1 }
}
var dic1 = ["test1": 1]
dic1 += ["test2": 2]
dic1 // ["test2": 2, "test1": 1]
Ответ 6
Попробуйте этот подход
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;
};
}
Надеюсь, что это поможет!
Ответ 7
Мои потребности были разные, я хотел слиться и не ссориться.
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)")
Ответ 8
Вы можете использовать приведенный ниже код для объединения двух экземпляров словаря в Swift:
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
}
}
Ответ 9
Вы используете слово let для объявления словаря, чтобы не вносить изменения в словарь, поскольку он используется для объявления константы.
Измените его на ключевое слово var, и оно будет работать для вас.
var dict1: [String: AnyObject] = [
kFacebook: [
kToken: token
]
]
var dict2: [String: AnyObject] = [
kRequest: [
kTargetUserId: userId
]
]
dict1 += dict2
Ответ 10
let dict1: [String: AnyObject] = [
"kFacebook": [
"kToken": "token"
]
]
let dict2: [String: AnyObject] = [
"kRequest": [
"kTargetUserId": "userId"
]
]
var ArrayOfDictionary = [dict1,dict2]
println(ArrayOfDictionary)
Отпечатано
[[kFacebook: {
kToken = token;
}], [kRequest: {
kTargetUserId = userId;
}]]