2011-06-29 32 views
19

construir scala.collection.Map de otras colecciones, encuentro constantemente a mí mismo escribiendoScala Mapa de tupla iterables

val map = Map(foo.map(x=>(x, f(x)))

Sin embargo, esto no funciona muy bien, ya Map.apply tarda sólo argumentos variables - por lo que tengo que escribir

val map = Map(foo.map(x=>(x, f(x)) toSeq :_*)

para obtener lo que quiero, pero parece doloroso. ¿Hay una forma más bonita de construir un Map desde un Iterable de tuplas?

Respuesta

28

Use TraversableOnce.toMap que se define si los elementos de un Traversable/Iterable son del tipo Tuple2. (API)

val map = foo.map(x=>(x, f(x)).toMap 
+1

O, 'foo.mapValues ​​(f) .toMap'. – missingfaktor

+0

@missingfaktor es mapValues ​​un método para las clases que no sean Map? – juanchito

+0

@mayonesa, no, pero creo que no sabía nada mejor en ese momento. :) – missingfaktor

4

Alternativamente, puede utilizar el uso collection.breakOut como la implícita CanBuildFrom argumento para la llamada map; esto elegirá un generador de resultados basado en el tipo esperado.

scala> val x: Map[Int, String] = (1 to 5).map(x => (x, "-" * x))(collection.breakOut) 
x: Map[Int,String] = Map(5 -> -----, 1 -> -, 2 -> --, 3 -> ---, 4 -> ----) 

Se llevará a cabo mejor que la versión .toMap, ya que sólo se itera la colección una vez.

No es tan obvio, pero esto también funciona con una comprensión.

scala> val x: Map[Int, String] = (for (i <- (1 to 5)) yield (i, "-" * i))(collection.breakOut) 
x: Map[Int,String] = Map(5 -> -----, 1 -> -, 2 -> --, 3 -> ---, 4 -> ----) 
+0

Gracias por esto - aunque no voy a usarlo en el código que otras personas tienen que leer sin pegar en enlaces a las numerosas explicaciones de la locura 'CanBuildFrom', * es * útil para el caso en el que deseo para convertir un rango inmutable a 'mutable.Map', donde la respuesta que acepté antes solo me da un error de tipo. – themel

2
val map = foo zip (foo map f) toMap