2009-07-30 5 views
8

(Ceci est une variante à this Q&A)Scala meilleur moyen de transformer une collection en carte-par-clé? (2e variante)

Dire que j'ai ceci:

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

Je veux créer une carte pour laquelle la clé est la longueur de la chaîne et la valeur est une collection de toutes les chaînes qui ont cette longueur. En d'autres termes, compte tenu de la liste au sujet, nous obtiendrions:

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

Le code que j'ai écrit pour ce faire est:

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

Cela fonctionne, mais il ajoute beaucoup de laideur la réponse élégante donnée par Daniel Spiewak à la question originale (référencée ci-dessus).

Des idées pour améliorer la solution pour ma variante?

Merci! Sean

Répondre

7

Si cela ne vous dérange pas les performances moche:

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

Le problème est que la liste est lue à nouveau pour chaque longueur différente.

Maintenant, au sujet de la laideur de votre version, peut-être cette aide:

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

mieux? Ce n'est toujours pas très bon parce que vous obtenez la longueur deux fois. Celui-ci n'a pas ce problème, mais il est un peu plus laid:

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

Je ne trouve pas la dernière variante moche, si val longueur est raccourci à val l. Les variables à lettre unique dans scala sont souvent utilisées dans un style scala similaire aux formules mathématiques, c'est-à-dire que vous déclarez la signification d'une variable d'espace réservé, puis l'utilisez. Parce que cela conduit à des expressions très courtes (le plus souvent des doublures), le nom court qui serait considéré comme cryptique dans d'autres langues n'est pas un problème dans la pratique. – Palimondo

+0

@Palimondo Ce n'est pas la longueur qui m'énerve. Je n'aime pas casser le calcul dans deux déclarations. Malheureusement, Scala ne peut pas optimiser 's.length' pour réutiliser la valeur, comme le ferait Haskell. –

19

Avec Scala 2.8.0:

list.groupBy(_.length) 

Il ne peut pas être plus simple que ça!

+0

Je pense que c'est très élégant, mais je ne comprends pas pourquoi le tri est nécessaire. Pouvez-vous l'expliquer? Merci. – agilefall

+1

@agilefall: tu as raison. le tri n'est pas nécessaire. Merci! –

Questions connexes