2009-07-30 18 views
8

(Esta es una variante de this Q&A)¿La mejor manera de Scala de convertir una colección en un mapa por clave? (Segunda variante)

Decir que tengo esto:

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

Quiero crear un mapa para el que la clave es la longitud de la cadena y el valor se una colección de todas las cadenas que tienen esa longitud. En otras palabras, dada la Lista aproximadamente, que tendríamos:

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

El código que he escrito para hacer esto es:

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

Esto funciona, pero se añade una gran cantidad de fealdad a la elegante respuesta que Daniel Spiewak brindó a la pregunta original (mencionada anteriormente).

¿Alguna idea de cómo mejorar la solución para mi variante?

Gracias! Sean

Respuesta

7

Si no te importa el rendimiento pésimo:

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

El problema es que la lista se lee de nuevo para cada longitud diferente.

Ahora, sobre la fealdad de su versión, tal vez esto ayuda:

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

mejor? Todavía no es tan bueno porque tienes la longitud dos veces. Éste no tiene este problema, pero es un poco más feo:

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

No encuentro la última variante fea, si val longitud se acorta a vall. Las variables de una sola letra en scala a menudo se usan en scala en un estilo similar a las fórmulas matemáticas, es decir, usted declara el significado de una variable de marcador de posición y luego solo la usa. Debido a que esto lleva a expresiones muy cortas (más a menudo líneas), el nombre corto que se consideraría críptico en otros idiomas no es un problema en la práctica. – Palimondo

+0

@Palimondo No es la longitud lo que me molesta. No me gusta romper el cálculo en dos declaraciones. Desafortunadamente, Scala no puede optimizar 's.length' para reutilizar el valor, como lo haría Haskell. –

19

Con Scala 2.8.0:

list.groupBy(_.length) 

No puede ser más simple que eso!

+0

Creo que esto es muy elegante, pero no entiendo por qué es necesario el género. ¿Puedes explicarlo? Gracias. – agilefall

+1

@agilefall: tienes razón. ordenar no es necesario. ¡Gracias! –

Cuestiones relacionadas