2011-08-09 19 views
23

Tengo un mapa que necesito asignar a un tipo diferente, y el resultado debe ser una lista. Tengo dos formas (aparentemente) de lograr lo que quiero, ya que llamar al mapa en un mapa parece dar como resultado siempre un mapa. Suponiendo que tengo algo de mapa que se parece a:Conversión de un mapa de Scala en una lista

val input = Map[String, List[Int]]("rk1" -> List(1,2,3), "rk2" -> List(4,5,6)) 

puedo o bien hacer:

val output = input.map{ case(k,v) => (k.getBytes, v) } toList 

O:

val output = input.foldRight(List[Pair[Array[Byte], List[Int]]]()){ (el, res) => 
    (el._1.getBytes, el._2) :: res 
} 

En el primer ejemplo puedo convertir el tipo, y luego llamar a toList . Supongo que el tiempo de ejecución es algo así como O(n*2) y el espacio requerido es n*2. En el segundo ejemplo, convierto el tipo y genero la lista de una vez. Supongo que el tiempo de ejecución es O(n) y el espacio requerido es n.

Mi pregunta es, ¿son esencialmente idénticas o la segunda conversión reduce la memoria/tiempo/etc.? Además, ¿dónde puedo encontrar información sobre el almacenamiento y los costos de tiempo de ejecución de varias conversiones de scala?

Gracias de antemano.

Respuesta

23

Mi forma favorita de hacer este tipo de cosas es como esto:

input.map { case (k,v) => (k.getBytes, v) }(collection.breakOut): List[(Array[Byte], List[Int])] 

Con esta sintaxis, que están pasando a map el constructor tiene que reconstruir la colección resultante. (En realidad, no es un constructor, sino una fábrica de constructores. Obtenga más información acerca de Scala's CanBuildFrom s si está interesado.) collection.breakOut puede usarse exactamente cuando desee cambiar de un tipo de colección a otro mientras hace un map, flatMap, etc. la única parte mala es que tienes que usar la anotación de tipo completo para que sea efectiva (aquí, utilicé una adscripción de tipo después de la expresión). Entonces, no se está compilando una colección intermediaria, y la lista está construida mientras que el mapeo.

+3

+1. Para aquellos que buscan entender cómo funciona 'breakOut', consulte la excelente respuesta de Daniel Sobral, http://stackoverflow.com/questions/1715681/scala-2-8-breakout/1716558#1716558 –

18

Mapeo sobre una vista en el primer ejemplo podría reducir la necesidad de espacio para un gran mapa:

val output = input.view.map{ case(k,v) => (k.getBytes, v) } toList 
+0

Acerca de las vistas vagas: http: // www .scala-lang.org/docu/files/collections-api/collections_42.html – Vadzim

Cuestiones relacionadas