Ich möchte eine Funktion auf alle Tasten im Wörterbuch abbilden. Ich hatte gehofft, dass so etwas wie das Folgende funktionieren würde, aber der Filter kann nicht direkt auf das Wörterbuch angewendet werden. Was ist der sauberste Weg, um dies zu erreichen?
In diesem Beispiel versuche ich, jeden Wert um 1 zu erhöhen. Dies ist jedoch für das Beispiel zufällig. Der Hauptzweck besteht darin, herauszufinden, wie map () auf ein Wörterbuch angewendet wird.
var d = ["foo" : 1, "bar" : 2]
d.map() {
$0.1 += 1
}
swift
dictionary
Maria Zverina
quelle
quelle
map
Fall ist. Was Sie verlangen, ist eine Möglichkeit, die Iteration hinter einer Erweiterung / Schließung zu verbergen, damit Sie sie nicht jedes Mal betrachten müssen, wenn Sie sie verwenden.Antworten:
Swift 4+
Gute Nachrichten! Swift 4 enthält eine
mapValues(_:)
Methode, die eine Kopie eines Wörterbuchs mit denselben Schlüsseln, aber unterschiedlichen Werten erstellt. Es enthält auch einefilter(_:)
Überlast , die eine RückkehrDictionary
undinit(uniqueKeysWithValues:)
undinit(_:uniquingKeysWith:)
Initialisierungen a erzeugenDictionary
aus einer beliebigen Sequenz von Tupeln. Das heißt, wenn Sie sowohl die Schlüssel als auch die Werte ändern möchten, können Sie Folgendes sagen:Es gibt auch neue APIs zum Zusammenführen von Wörterbüchern, zum Ersetzen fehlender Elemente durch einen Standardwert, zum Gruppieren von Werten (Konvertieren einer Sammlung in ein Wörterbuch von Arrays, die durch das Ergebnis der Zuordnung der Sammlung zu einer bestimmten Funktion gekennzeichnet sind) und vieles mehr.
Während der Diskussion des Vorschlags SE-0165 , der diese Funktionen einführte, habe ich diese Antwort zum Stapelüberlauf mehrmals angesprochen, und ich denke, die schiere Anzahl von Upvotes hat dazu beigetragen, die Nachfrage zu demonstrieren. Vielen Dank für Ihre Hilfe, um Swift besser zu machen!
quelle
map
, der zu widersprüchlichen Schlüsseln führen kann, istmap
in vielen Situationen immer noch nützlich . (Andererseits könnte man argumentieren, dass das Zuordnen nur der Werte eine natürliche Interpretation vonmap
Wörterbüchern ist - sowohl das Beispiel des Originalplakats als auch mein Beispiel ändern nur die Werte, und konzeptionellmap
ändert ein Array in einem Array nur die Werte, nicht die Indizes.)try
:return Dictionary<Key, OutValue>(try map { (k, v) in (k, try transform(v)) })
DictionaryExtension.swift:13:16: Argument labels '(_:)' do not match any available overloads
Argument labels '(_:)' do not match any available overloads
bei der Implementierung diese letzte Erweiterung. Ich bin mir nicht sicher, wie ich es lösen soll: /Dictionary
Initialisierer ab, der in einem der vorherigen Beispiele hinzugefügt wurde. Stellen Sie sicher, dass Sie beide einschließen.Mit Swift 5 können Sie eines der fünf folgenden Snippets verwenden, um Ihr Problem zu lösen.
# 1. Mit
Dictionary
mapValues(_:)
Methode# 2. Mit
Dictionary
map
Methode undinit(uniqueKeysWithValues:)
Initialisierer#3. Verwendung
Dictionary
reduce(_:_:)
Methode oderreduce(into:_:)
Verfahren# 4. Mit
Dictionary
subscript(_:default:)
Index# 5. Mit
Dictionary
subscript(_:)
Indexquelle
Während sich die meisten Antworten hier darauf konzentrieren, wie das gesamte Wörterbuch (Schlüssel und Werte) zugeordnet wird, wollte die Frage eigentlich nur die Werte zuordnen. Dies ist eine wichtige Unterscheidung, da Sie durch die Zuordnung von Werten die gleiche Anzahl von Einträgen garantieren können, während die Zuordnung von Schlüssel und Wert zu doppelten Schlüsseln führen kann.
Hier ist eine Erweiterung,
mapValues
mit der Sie nur die Werte zuordnen können. Beachten Sie, dass das Wörterbuch auch uminit
eine Folge von Schlüssel / Wert-Paaren erweitert wird, was etwas allgemeiner ist als die Initialisierung über ein Array:quelle
func mapValues<T>(_ transform: (_ value: Value) -> T) -> [Key: T] { var result = [Key: T]() for (key, val) in self { result[key] = transform(val) } return result }
. Ich finde es liest sich auch besser. Gibt es ein Leistungsproblem?Der sauberste Weg ist, einfach
map
zum Wörterbuch hinzuzufügen :Überprüfen, ob es funktioniert:
Ausgabe:
quelle
SequenceType.map
es sich nicht um eine mutierende Funktion handelt. Ihr Beispiel könnte umgeschrieben werden, um dem bestehenden Vertrag für zu folgenmap
, aber das entspricht der akzeptierten Antwort.Sie können auch
reduce
anstelle der Karte verwenden.reduce
ist in der Lage etwas zu tun ,map
und mehr tun können!Es wäre ziemlich einfach, dies in eine Erweiterung zu packen, aber auch ohne die Erweiterung können Sie mit einem Funktionsaufruf das tun, was Sie wollen.
quelle
let newDict = oldDict.reduce([String:Int]()) { (var dict, pair) in dict["new\(pair.1)"] = pair.1; return dict }
Es stellt sich heraus, dass Sie dies tun können. Sie müssen lediglich ein Array aus der
MapCollectionView<Dictionary<KeyType, ValueType>, KeyType>
von den Wörterbüchern zurückgegebenenkeys
Methode erstellen . ( Info hier ) Sie können dieses Array dann zuordnen und die aktualisierten Werte an das Wörterbuch zurückgeben.quelle
Gemäß der Swift Standard Library Reference ist map eine Funktion von Arrays. Nicht für Wörterbücher.
Sie können Ihr Wörterbuch jedoch iterieren, um die Schlüssel zu ändern:
quelle
Ich suchte nach einer Möglichkeit, ein Wörterbuch direkt in ein typisiertes Array mit benutzerdefinierten Objekten abzubilden. Die Lösung in dieser Erweiterung gefunden:
Verwenden Sie es wie folgt:
quelle
Swift 3
Ich versuche einen einfachen Weg in Swift 3.
Ich möchte Karte [String: String] zu [String: String] , verwende ich forEach statt Karte oder flache Karte.
quelle
Swift 5
Die Kartenfunktion des Wörterbuchs wird mit dieser Syntax geliefert.
dictData.map(transform: ((key: String, value: String)) throws -> T)
Sie können einfach Abschlusswerte festlegen
Die Ausgabe erfolgt ::
Es kann diese Warnung geben
Result of call to 'map' is unused
Dann einfach
_ =
vor Variable setzen.Vielleicht hilft es Ihnen. Danke.
quelle
Ich gehe davon aus, dass das Problem darin besteht, die Schlüssel unseres ursprünglichen Wörterbuchs beizubehalten und alle seine Werte auf irgendeine Weise zuzuordnen.
Lassen Sie uns verallgemeinern und sagen, dass wir möglicherweise alle Werte einem anderen Typ zuordnen möchten .
Wir möchten also mit einem Wörterbuch und einem Abschluss (einer Funktion) beginnen und am Ende ein neues Wörterbuch erhalten. Das Problem ist natürlich, dass Swifts strenge Eingabe im Weg steht. Ein Abschluss muss angeben, welcher Typ eingeht und welcher Typ herauskommt. Daher können wir keine Methode erstellen, die einen allgemeinen Abschluss erfordert - außer im Kontext eines Generikums. Wir brauchen also eine generische Funktion.
Andere Lösungen haben sich darauf konzentriert, dies innerhalb der generischen Welt der generischen Dictionary-Struktur selbst zu tun, aber ich finde es einfacher, in einer Funktion der obersten Ebene zu denken. Zum Beispiel könnten wir dies schreiben, wobei K der Schlüsseltyp ist, V1 der Werttyp des Startwörterbuchs ist und V2 der Werttyp des Endwörterbuchs ist:
Hier ist ein einfaches Beispiel für den Aufruf, um zu beweisen, dass sich das Generikum beim Kompilieren tatsächlich von selbst auflöst:
Wir begannen mit einem Wörterbuch von
[String:Int]
und endeten mit einem Wörterbuch von,[String:String]
indem wir die Werte des ersten Wörterbuchs durch einen Abschluss transformierten.(BEARBEITEN: Ich sehe jetzt, dass dies effektiv mit der Lösung von AirspeedVelocity identisch ist, außer dass ich nicht die zusätzliche Eleganz eines Dictionary-Initialisierers hinzugefügt habe, der ein Dictionary aus einer Zip-Sequenz macht.)
quelle
Swift 3
Verwendung:
Erweiterung:
quelle
Wenn Sie nur versuchen, die Werte zuzuordnen (möglicherweise ihren Typ zu ändern), fügen Sie diese Erweiterung hinzu:
Vorausgesetzt, Sie haben dieses Wörterbuch:
Die einzeilige Werttransformation sieht dann folgendermaßen aus:
Die mehrzeilige Werttransformation sieht dann folgendermaßen aus:
quelle
Ein anderer Ansatz ist
map
ein Wörterbuch undreduce
, wo FunktionenkeyTransform
undvalueTransform
Funktionen sind.quelle
Swift 3 Ich habe das benutzt,
Verwendung:
Ref
quelle