Wenn ich eine Sammlung c
von Typen habe T
und eine Eigenschaft p
für T
(z P
. B. Typ ) vorhanden ist, wie kann ich einen Map-by-Extracting-Key am besten erstellen ?
val c: Collection[T]
val m: Map[P, T]
Ein Weg ist der folgende:
m = new HashMap[P, T]
c foreach { t => m add (t.getP, t) }
Aber jetzt brauche ich eine veränderbare Karte. Gibt es eine bessere Möglichkeit, dies so zu tun, dass es in einer Zeile steht und ich eine unveränderliche Karte erhalte ? (Natürlich könnte ich das oben genannte in ein einfaches Bibliotheksdienstprogramm verwandeln, wie ich es in Java tun würde, aber ich vermute, dass es in Scala keine Notwendigkeit gibt)
scala
map
scala-collections
oxbow_lakes
quelle
quelle
Traversable[K].mapTo( K => V)
undTraversable[V].mapBy( V => K)
waren besser!c
durchc.iterator
, um die Erstellung einer Zwischensammlung zu vermeiden.Sie können eine Karte mit einer variablen Anzahl von Tupeln erstellen. Verwenden Sie also die Map-Methode für die Sammlung, um sie in eine Sammlung von Tupeln zu konvertieren, und verwenden Sie dann den Trick: _ *, um das Ergebnis in ein variables Argument zu konvertieren.
quelle
Zusätzlich zur Lösung von @James Iry ist dies auch mit einer Falte möglich. Ich vermute, dass diese Lösung etwas schneller ist als die Tupelmethode (es werden weniger Müllobjekte erstellt):
quelle
list.foldLeft(Map[String,Int]()) { (m,s) => m + (s -> s.length) }
. Beachten Sie, dass Sie ein zusätzliches Klammerpaar benötigen, wenn Sie das Tupel mit Komma erstellen möchten :((s, s.length))
.Dies kann unveränderlich und mit einer einzigen Durchquerung implementiert werden, indem die Sammlung wie folgt gefaltet wird.
Die Lösung funktioniert, weil das Hinzufügen zu einer unveränderlichen Karte eine neue unveränderliche Karte mit dem zusätzlichen Eintrag zurückgibt und dieser Wert während der Faltoperation als Akkumulator dient.
Der Kompromiss hier ist die Einfachheit des Codes gegenüber seiner Effizienz. Für große Sammlungen ist dieser Ansatz möglicherweise besser geeignet als die Verwendung von zwei Durchquerungsimplementierungen, z. B. Anwenden von
map
undtoMap
.quelle
Eine andere Lösung (funktioniert möglicherweise nicht für alle Typen)
Dadurch wird die Erstellung der Zwischenliste vermieden. Weitere Informationen finden Sie hier: Scala 2.8 breakOut
quelle
Was Sie erreichen wollen, ist etwas undefiniert.
Was ist, wenn zwei oder mehr Elemente
c
dasselbe teilenp
? Welches Element wird demp
in der Karte zugeordnet?Die genauere Sichtweise besteht darin, eine Karte zwischen
p
und allenc
Elementen zu erstellen, die sie haben:Dies könnte leicht mit groupBy erreicht werden :
Wenn Sie die ursprüngliche Karte weiterhin möchten, können Sie beispielsweise
p
die erste Karte zuordnen , diet
sie enthält:quelle
collect
anstelle vonmap
. ZB :c.group(t => t.p) collect { case (Some(p), ts) => p -> ts.head }
. Auf diese Weise können Sie beispielsweise Karten reduzieren, wenn Sie eine Option [_] eingeben..mapValues(_.head)
anstelle der Karte verwenden.Dies ist wahrscheinlich nicht die effizienteste Methode, um eine Liste in eine Karte umzuwandeln, macht den aufrufenden Code jedoch besser lesbar. Ich habe implizite Konvertierungen verwendet, um List eine mapBy- Methode hinzuzufügen :
Beispiel für einen Aufrufcode:
Beachten Sie, dass der Aufrufercode aufgrund der impliziten Konvertierung die implicitConversions von scala importieren muss.
quelle
Funktioniert gut und ist sehr intuitiv
quelle
c
als Schlüssel (Art) zu einer "Karte" kombiniert . Beachten Sie "map", da die resultierende Sammlung keine Scala ist,Map
sondern eine andere Liste / Iterable von Tupeln erstellt ... aber der Effekt ist der gleiche für den Zweck des OP. Ich würde die Einfachheit nicht außer Acht lassen, aber sie ist nicht so effizient wie diefoldLeft
Lösung und auch nicht die eigentliche Antwort auf die Frage "Umwandlung in eine Sammlung in eine Karte nach Schlüssel"Wie wäre es mit zip und toMap?
quelle
Für das, was es wert ist, gibt es zwei sinnlose Möglichkeiten:
quelle
Map.fromList $ map (bar &&& id) c
,Map.fromList $ map (bar >>= (,)) c
.Das funktioniert bei mir:
Die Karte muss veränderbar sein und die Karte muss zurückgegeben werden, da das Hinzufügen zu einer veränderlichen Karte keine Karte zurückgibt.
quelle
val personsMap = persons.foldLeft(Map[Int, PersonDTO]()) { (m, p) => m + (p.id -> p) }
Die Karte kann unveränderlich sein, wie oben gezeigt, da das Hinzufügen zu einer unveränderlichen Karte eine neue unveränderliche Karte mit dem zusätzlichen Eintrag zurückgibt. Dieser Wert dient als Akkumulator während der Falzoperation.Verwenden Sie map () für die Sammlung, gefolgt von toMap
quelle
Bei der Konvertierung von Json String (Lesen einer Json-Datei) in Scala Map
quelle