2009-07-30 11 views
8

(jest to wariant do this Q&A)Scala najlepszy sposób przekształcenia kolekcji w mapę po klawiszu? (2 wariant)

Say mam to:

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

Chcę utworzyć mapę do którego klucz jest długość ciągów i wartość jest Zbiór wszystkich łańcuchów, które mają taką długość. Innymi słowy, biorąc pod uwagę Lista o, to otrzymujemy:

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

Kod Pisałem to zrobić:

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

To działa, ale to dodaje wiele do brzydoty elegancka odpowiedź Daniela Śpiewaka na oryginalne pytanie (wspomniane powyżej).

Jakieś pomysły, jak ulepszyć rozwiązanie dla mojego wariantu?

Dzięki! Sean

Odpowiedz

7

Jeśli nie przeszkadza kiepska wydajność:

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: _*) 

Problemem jest to, że lista jest ponownie przeczytać na każdej różnej długości.

Teraz o uglyness swojej wersji, może to pomoże:

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

lepsze? Wciąż nie jest całkiem dobrze, ponieważ dostajesz dwukrotnie długość. Ten nie ma tego problemu, ale jest to nieco brzydsze:

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

Nie uważam ostatniego wariantu za brzydki, jeśli długość val jest skrócona do val l. Zmienne jednoliterowe w scala są często używane w scala w stylu podobnym do formuł matematycznych, tzn. Deklarujesz znaczenie zmiennej zastępczej, a następnie po prostu ją używasz. Ponieważ prowadzi to do bardzo krótkich wyrażeń (najczęściej jednej linijki), krótka nazwa, która w innych językach jest uważana za tajemniczą, nie stanowi problemu w praktyce. – Palimondo

+0

@Palimondo To nie długość mnie drażni. Nie lubię przerywać obliczeń w dwóch wypowiedziach. Niestety, Scala nie może zoptymalizować 's.length', aby ponownie użyć wartości, jak zrobiłby to Haskell. –

19

Z Scala 2.8.0:

list.groupBy(_.length) 

Nie można było prostsze niż to!

+0

Myślę, że to bardzo eleganckie, ale nie rozumiem, dlaczego ten rodzaj jest potrzebny. Możesz to wyjaśnić? Dzięki. – agilefall

+1

@agilefall: masz rację. sortowanie nie jest potrzebne. dzięki! –

Powiązane problemy