2009-07-30 11 views
8

(Dies ist eine Variante zu this Q&A)Scala der beste Weg, eine Sammlung in eine Map-by-Key zu verwandeln? (2. Variante)

Sagen, ich habe dies:

List("foo", "bar", "spam") 

Ich möchte eine Karte erstellen, für die der Schlüssel ist die Länge des String ist und der Wert ist Eine Sammlung aller Strings mit dieser Länge. Mit anderen Worten, die etwa Liste gegeben, würden wir bekommen:

Map(3 -> List(foo, bar), 4 -> List(spam)) 

Der Code, den ich geschrieben habe, dies zu tun ist:

list.foldLeft(Map[Long, List[String]]()) { 
    (m, s) => m(s.length) = s :: 
    (if (m.contains(s.length)) m(s.length) 
     else Nil) 
} 

Dies funktioniert, aber es fügt eine Menge von Hässlichkeit die elegante Antwort, die Daniel Spiewak auf die ursprüngliche Frage gegeben hat (siehe oben).

Irgendwelche Ideen, wie man die Lösung für meine Variante verbessert?

Danke! Sean

Antwort

7

Wenn Sie nicht miese Leistung nichts dagegen:

val list = List("foo", "bar", "spam") 
val keyValue = for (length <- list map (_ length) removeDuplicates; 
        strings = list filter (_.length == length)) 
       yield (length -> strings) 
val map = Map(keyValue: _*) 

Das Problem ist, dass die Liste wieder für jede unterschiedliche Länge gelesen wird.

nun über die uglyness Ihrer Version, vielleicht das hilft:

list.foldLeft(Map[Long, List[String]]()) { 
    (m, s) => m(s.length) = s :: m.getOrElse(s.length, Nil) 
} 

besser? Es ist immer noch nicht ganz gut, weil du die Länge zweimal bekommst. Dieses Appartment hat dieses Problem nicht, aber es ist etwas hässlicher:

list.foldLeft(Map[Long, List[String]]()) { 
    (m, s) => val length = s.length; m(length) = s :: m.getOrElse(length, Nil) 
} 
+0

Ich finde die letzte Variante nicht hässlich, wenn val Länge auf val l verkürzt wird. Variablen mit einem Buchstaben in scala werden häufig in scala ähnlich wie mathematische Formeln verwendet, d. H. Sie deklarieren die Bedeutung einer Platzhaltervariablen und verwenden sie dann einfach. Da dies zu sehr kurzen Ausdrücken führt (meistens ein Liner), ist der Kurzname, der in anderen Sprachen als kryptisch angesehen würde, in der Praxis kein Problem. – Palimondo

+0

@Palimondo Es ist nicht die Länge, die mich nervt. Ich mag es nicht, die Berechnung in zwei Aussagen zu brechen. Leider kann Scala 's.length' nicht optimieren, um den Wert wiederzuverwenden, wie es Haskell tun würde. –

19

Mit Scala 2.8.0:

list.groupBy(_.length) 

Es kann nicht einfacher als das!

+0

Ich denke, das ist sehr elegant, aber ich verstehe nicht, warum die Sorte benötigt wird. Kannst du es erklären? Vielen Dank. – agilefall

+1

@agilefall: Du hast Recht. Sortierung wird nicht benötigt. Vielen Dank! –

Verwandte Themen