2010-07-24 40 views
6

En Python, un diccionario puede ser construido a partir de una colección iterable de tuplas:Scala: cómo crear un mapa inmutable a partir de una colección de Tuple2s?

>>> listOfTuples = zip(range(10), [-x for x in range(10)]) 
>>> listOfTuples 
[(0, 0), (1, -1), (2, -2), (3, -3), (4, -4), (5, -5), (6, -6), (7, -7), (8, -8), (9, -9)] 
>>> theDict = dict(listOfTuples) 
>>> theDict 
{0: 0, 1: -1, 2: -2, 3: -3, 4: -4, 5: -5, 6: -6, 7: -7, 8: -8, 9: -9} 
>>> 

¿Existe una sintaxis Scala equivalente? Veo que puede usar una cantidad de tipo variegs de Tuple2s para construir un mapa, p.

scala> val theMap = Map((0,0),(1,-1)) 
theMap: scala.collection.immutable.Map[Int,Int] = Map((0,0), (1,-1)) 

scala> theMap(0) 
res4: Int = 0 

scala> theMap(1) 
res5: Int = -1 

scala> val tuplePairs = List((0,0),(1,-1)) 
tuplePairs: List[(Int, Int)] = List((0,0), (1,-1)) 

scala> val mapFromIterable = Map(tuplePairs) 
<console>:6: error: type mismatch; 
found : List[(Int, Int)] 
required: (?, ?) 
     val mapFromIterable = Map(tuplePairs) 
           ^

Pude recorrer y asignar cada valor manualmente, pero parece que debe haber una forma mejor.

scala> var theMap:scala.collection.mutable.Map[Int,Int] = scala.collection.mutable.Map() 
theMap: scala.collection.mutable.Map[Int,Int] = Map() 

scala> tuplePairs.foreach(x => theMap(x._1) = x._2)          

scala> theMap 
res13: scala.collection.mutable.Map[Int,Int] = Map((1,-1), (0,0)) 

Respuesta

10

usando Scala 2.8.0 final, puede hacerlo de esta manera:


scala> val tuplePairs = List((0,0),(1,-1)) 
tuplePairs: List[(Int, Int)] = List((0,0), (1,-1)) 

scala> tuplePairs.toMap 
res0: scala.collection.immutable.Map[Int,Int] = Map((0,0), (1,-1)) 

Si está utilizando Scala 2.7.7 se podría hacer algo así, como una alternativa al método que se usado:


scala> val tuplePairs = List((0,0),(1,-1)) 
tuplePairs: List[(Int, Int)] = List((0,0), (1,-1)) 

scala> Map(tuplePairs: _*) 
res2: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1) 

pero como puede ver, en 2.8.0 las cosas se han mejorado mucho.

+0

toMap funcionó muy bien. Mucho más claro que la sintaxis ++. – I82Much

+3

El 'mapa' en la respuesta 2.7 no es necesario. 'Map() ++ tuplePairs' haría, al igual que' Map (tuplePairs: _ *) '. –

+0

De hecho, tienes razón, por supuesto, gracias –

2

Hay varias opciones. Primero (pero no recomendado, IMO), puede convertir un List en un varargs usando list:_* Alternativamente, puede usar algo como la función ++ para agregar una lista de valores en un mapa (que es lo que Map.apply hace de todos modos)

scala> (Map[Int,Int]()) ++ List((1,2),(3,4)) 
res4: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4) 

scala> Map(List((1,2),(3,4)):_*) 
res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4) 
+0

¿Por qué mis mapas impresos como mapa ((1, -1), (0, 0)) mientras que los suyos van al mapa impreso más bonito (1 -> -1, 0 -> 0)? ¿Alguna idea? – I82Much

+0

Esto funciona perfectamente. Gracias. – I82Much

+0

Ninguna pista, en realidad. ¿Alguien más sabe? Hmm, esta terminal todavía es 2.7.7, ¿es por eso? –

4

Si bien hay algunas respuestas que dan buenos consejos, esto es lo que creo que está más cerca del código python original.

// Scala 2.8 
val listOfTuples = (0 until 10) zip (for (x <- 0 until 10) yield -x) 
val theMap = Map(listOfTuples:_*) 

Scala 2.7 no tienen zip en rangos, sin embargo, por lo tanto, usted tiene que convertir los rangos de listas en la primera asignación:

// Scala 2.7 
val listOfTuples = (0 until 10).toList zip (for (x <- 0 until 10) yield -x).toList 
val theMap = Map(listOfTuples:_*) 
2

no puedo dejar un comentario a la respuesta aceptada (no reputación suficiente aún), pero la solución propuesta para Scala 2.7 es demasiado complejo:

scala> Map() ++ (tuplePairs map (t => (t._1,t._2))) 
res2: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1) 

el "mapa" es no hacer nada, es la conversión de un Tuple2 en un Tuple2. Esto es suficiente:

scala> Map() ++ tuplePairs 
res3: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1) 

En mis ojos sería aún mejor usar Map.empty:

scala> Map.empty ++ tuplePairs 
res4: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1) 
+1

Gracias por la información. Nunca hubiera encontrado el método ++ ... ¿cómo puedes buscar eso? – I82Much

+0

Usar ++ no era mi idea, simplemente eliminé el mapa innecesario. Lamentablemente, los 2,7 scaladocs parecen haberse eliminado de scala-lang.org, pero el ++ de un mapa [A, B] se describe allí. – bseibold

Cuestiones relacionadas