Tablice w języku Swift obsługują operator + = w celu dodania zawartości jednej tablicy do drugiej. Czy istnieje łatwy sposób na zrobienie tego w przypadku słownika?
na przykład:
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var combinedDict = ... (some way of combining dict1 & dict2 without looping)
dictionary
swift
rustyshelf
źródło
źródło
fromDict.forEach {intoDict[$0] = $1}
Odpowiedzi:
Możesz zdefiniować
+=
operatorDictionary
np.źródło
@assignment
ireturn
, już mutujesz left. Edycja: właściwie, chociaż nie dostaję żadnych błędów, myślę, że@assignment
powinienem zostać.func +=<K, V> (inout left: [K : V], right: [K : V]) { for (k, v) in right { left[k] = v } }
public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) { rhs.forEach({ lhs[$0] = $1}) }
W Swift 4 należy używać
merging(_:uniquingKeysWith:)
:Przykład:
źródło
[NSMutableDictionary addEntriesFromDictionary:]
.Co powiesz na
To dodaje wszystkie klucze i wartości dict2 do dict1.
źródło
Closure tuple parameter '(key: _, value: _)' does not support destructuring
(przynajmniej w momencie pisania tego tekstu). Trzeba byObecnie, patrząc na Swift Standard Library Reference for Dictionary, nie ma możliwości łatwej aktualizacji słownika innym.
Możesz napisać rozszerzenie, aby to zrobić
źródło
Swift 4 zapewnia
merging(_:uniquingKeysWith:)
, więc w Twoim przypadku:Zwraca skrótowe zamknięcie
$1
, dlatego wartość dict2 zostanie użyta w przypadku konfliktu z kluczami.źródło
- (void)addEntriesFromDictionary:(NSDictionary<KeyType, ObjectType> *)otherDictionary;
. W odniesieniu do tego, co zrobić z duplikatami, stwierdza on, że: „Jeśli oba słowniki zawierają ten sam klucz, poprzedni obiekt wartości słownika odbierającego dla tego klucza otrzymuje komunikat o zwolnieniu, a nowy obiekt wartości zajmuje jego miejsce.”, Więc w wersja Swift lub w merge (_: uniquingKeysWith :), zwracająca drugą wartość$1
, jest tym samym, coaddEntriesFromDictionary
robi.Nie jest wbudowany w bibliotekę Swift, ale możesz dodać to, co chcesz, z przeciążeniem operatora, np:
Powoduje to przeciążenie
+
operatora dla słowników, których możesz teraz użyć do dodania słowników za pomocą+
operatora, np .:źródło
map
i upuścić pierwsząfor (k, v)...
pętlę, jeśli zadeklarujeszleft
parametr jako,var
a następnie po prostu skopiujesz zright
niego wartości .+
operatora infix.+
przeciążenie operatora nie jest metodąDictionary
, jest to prosta funkcja. Zmiany wprowadzone wleft
parametrze zmiennej nie byłyby widoczne poza funkcją.Swift 3:
źródło
func merged(with dictionary: Dictionary<Key,Value>) -> Dictionary<Key,Value> {
var copy = self
dictionary.forEach { copy.updateValue($1, forKey: $0) }
return copy
}
Swift 2.0
źródło
union
Funkcja ma wartość przekazany do byćvar
, czyli skopiowany słownika może być zmutowany. Jest trochę czystszy niżfunc union(dictionary: Dictionary) -> Dictionary { var dict2 = dictionary; dict2.unionInPlace(self); return dict2 }
, choćby o jedną linię.var dictionary = dictionary
. Stąd: github.com/apple/swift-evolution/blob/master/propiments/…<Key, Value>
do tychDictionary
s.Niezmienny
Wolę łączyć / łączyć niezmienne słowniki z
+
operatorem, więc zaimplementowałem to tak:Zmienny
źródło
right.reduce(left)
, przynajmniej takie jest oczekiwane zachowanie imo (i jest to zachowanie z twojego drugiego przykładu) - tj.["A":1] + ["A":2]
powinno wyjść["A":2]
Nie ma teraz potrzeby posiadania żadnych rozszerzeń słownika. Słownik Swift (Xcode 9.0+) posiada odpowiednią funkcjonalność. Zajrzyj tutaj . Poniżej znajduje się przykład, jak go używać
źródło
oldDictionary.merge(newDictionary) { $1 }
Bardziej czytelny wariant z rozszerzeniem.
źródło
Możesz tego spróbować
źródło
Aby je scalić, możesz również użyć funkcji Redukcja. Spróbuj tego na placu zabaw
źródło
d
ip
?Polecam bibliotekę SwifterSwift . Jeśli jednak nie chcesz korzystać z całej biblioteki i wszystkich jej wspaniałych dodatków, możesz po prostu skorzystać z ich rozszerzenia Słownik:
Swift 3+
źródło
Możesz iterować po kombinacjach Key Value dla wartości, którą chcesz scalić i dodać je za pomocą metody updateValue (forKey :):
Teraz wszystkie wartości słownikTwo zostały dodane do DictionaryOne.
źródło
To samo, co odpowiedź @ farhadf, ale przyjęte dla Swift 3:
źródło
Swift 3, rozszerzenie słownika:
źródło
Niektóre jeszcze bardziej usprawnione przeciążenia dla Swift 4:
źródło
Możesz dodać takie
Dictionary
rozszerzenie :Wtedy użycie jest tak proste, jak następujące:
Jeśli wolisz ramy, która zawiera również kilka bardziej przydatne funkcje potem kasa HandySwift . Po prostu zaimportuj go do swojego projektu i możesz użyć powyższego kodu bez samodzielnego dodawania jakichkolwiek rozszerzeń do projektu.
źródło
Nie ma już potrzeby rozbudowy ani żadnej dodatkowej funkcji. Możesz napisać tak:
źródło
Możesz użyć,
źródło
Możesz użyć funkcji bridgeToObjectiveC (), aby uczynić słownik NSDictionary.
Będzie wyglądać następująco:
Następnie możesz przekonwertować NSDictionary (połączyć) z powrotem lub zrobić cokolwiek.
źródło
Wynikiem jest NSMutableDictionary, a nie słownik typu Swift, ale jego składnia jest taka sama (
out["a"] == 1
w tym przypadku), więc masz problem tylko wtedy, gdy używasz kodu innej firmy, który oczekuje słownika Swift, lub naprawdę Potrzebujesz sprawdzenia typu.Krótka odpowiedź jest taka, że faktycznie musisz zapętlić. Nawet jeśli nie wprowadzasz go jawnie, zrobi to wywoływana metoda (addEntriesFromDictionary: tutaj). Zasugerowałbym, jeśli nie masz pewności, dlaczego tak się dzieje, powinieneś rozważyć, w jaki sposób połączyć węzły liściowe dwóch drzew B.
Jeśli naprawdę potrzebujesz w zamian natywnego typu słownika Swift, proponuję:
Wadą tego podejścia jest to, że indeks słownika - jakkolwiek jest to zrobione - może być wielokrotnie przebudowywany w pętli, więc w praktyce jest to około 10x wolniejsze niż podejście NSMutableDictionary.
źródło
Wszystkie te odpowiedzi są skomplikowane. To jest moje rozwiązanie dla Swift 2.2:
źródło
Moje potrzeby były inne, musiałem scalić niekompletne zagnieżdżone zestawy danych bez klęczenia.
To było trudniejsze niż chciałem. Wyzwanie polegało na odwzorowaniu z dynamicznego pisania na statyczne i użyłem protokołów, aby rozwiązać ten problem.
Warto również zauważyć, że kiedy używasz składni literału słownikowego, w rzeczywistości otrzymujesz typy podstawowe, 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.
źródło
Swift 2.2
źródło
Po prostu skorzystałbym z biblioteki Dollar .
https://github.com/ankurp/Dollar/#merge---merge-1
Łączy wszystkie słowniki razem, a ten drugi słownik zastępuje wartość w danym kluczu
źródło
Oto fajne rozszerzenie, które napisałem ...
używać:
Następnie dict1 zostanie zmieniony na
źródło