Jak dołączyć jeden Dictionary
do drugiego Dictionary
za pomocą Swift
?
Korzystam z AlamoFire
biblioteki, aby wysłać plik JSON
do REST server
.
Słownik 1
var dict1: [String: AnyObject] = [
kFacebook: [
kToken: token
]
]
Słownik 2
var dict2: [String: AnyObject] = [
kRequest: [
kTargetUserId: userId
]
]
Jak połączyć te dwa słowniki, aby utworzyć nowy słownik, jak pokazano poniżej?
let parameters: [String: AnyObject] = [
kFacebook: [
kToken: token
],
kRequest: [
kTargetUserId: userId
]
]
Próbowałem, dict1 += dict2
ale wystąpił błąd kompilacji:
Operator binarny „+ =” nie może być zastosowany do dwóch operandów „[String: AnyObject]”
Odpowiedzi:
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)
Zapoznaj się z niesamowitym projektem Dollar & Cent https://github.com/ankurp/Cent/blob/master/Sources/Dictionary.swift
źródło
extension
aby było tofunction
dostępne w dowolnym miejscu mojego kodu? Przepraszam, jestem noobem![Key: Any]
)Dictionary
ma własne funkcje scalania. Zobacz stackoverflow.com/a/43615143/971329 .Uwielbiam to podejście:
dicFrom.forEach { (key, value) in dicTo[key] = value }
Swift 4 i 5
Dzięki Swift 4 Apple wprowadza lepsze podejście do łączenia dwóch słowników:
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]
Masz tutaj 2 opcje (jak w przypadku większości funkcji działających na kontenerach):
merge
mutuje istniejący słownikmerging
zwraca nowy słownikźródło
Dla Swift> = 2,2:
let parameters = dict1.reduce(dict2) { r, e in var r = r; r[e.0] = e.1; return r }
Dla Swift <2,2:
let parameters = dict1.reduce(dict2) { (var r, e) in r[e.0] = e.1; return r }
Swift 4 ma nową funkcję:
let parameters = dict1.reduce(into: dict2) { (r, e) in r[e.0] = e.1 }
To naprawdę ważne, aby grzebać standardowej biblioteki:
map
,reduce
,dropFirst
,forEach
itd. Są zszywki zwięzły kodu. Funkcjonalne bity są fajne!źródło
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]
źródło
SequenceType.forEach
(zaimplementowany przezDictionary
) zapewnia eleganckie rozwiązanie dodawania elementów słownika do innego słownika.dic1.forEach { dic2[$0] = $1 }
Na przykład
func testMergeDictionaries() { let dic1 = [1:"foo"] var dic2 = [2:"bar"] dic1.forEach { dic2[$0] = $1 } XCTAssertEqual(dic2[1], "foo") }
źródło
Możemy lepiej łączyć słowniki za pomocą słowa kluczowego merge
var dictionary = ["a": 1, "b": 2] /// Keeping existing value for key "a": dictionary.merge(["a": 3, "c": 4]) { (current, _) in current } // ["b": 2, "a": 1, "c": 4]
źródło
Moje potrzeby były inne, chciałem się scalić, a nie przebić.
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]]
Liczyłem na prostsze rozwiązanie, ale na tym skończyłem. Wyzwanie polegało na przeskakiwaniu od dynamicznego do statycznego pisania i użyłem protokołów do rozwiązania tego problemu.
Warto również zauważyć, że kiedy używasz składni literału słownikowego, w rzeczywistości otrzymujesz typy fundamentów, które nie odbierają rozszerzeń protokołu. Zrezygnowałem z wysiłków, aby je wspierać, ponieważ nie mogłem znaleźć łatwego sposobu na sprawdzenie jednolitości elementów kolekcji.
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)")
źródło
Wypróbuj to podejście
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)
Zostanie wydrukowany następujący:
}
Mam nadzieję, że to pomoże !!
źródło
Możesz użyć poniższego kodu, aby połączyć dwa wystąpienia słownika w 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 } }
źródło
Używasz słowa kluczowego let, aby zadeklarować słownik, więc nie możesz wprowadzać zmian w słowniku, ponieważ jest używany do deklarowania stałej.
Zmień to na słowo kluczowe var, a będzie działać dla Ciebie.
var dict1: [String: AnyObject] = [ kFacebook: [ kToken: token ] ] var dict2: [String: AnyObject] = [ kRequest: [ kTargetUserId: userId ] ] dict1 += dict2
źródło