2010-07-30 13 views
29

Quería agregar elementos dinámicamente en una matriz. Pero parece que las matrices y listas de Scala no proporcionan ningún método para agregar elementos dinámicamente debido a la naturaleza inmutable.¿Cuál es la mejor manera de crear una matriz de crecimiento dinámico en Scala?

Así que decidí usar el tipo de datos de lista para hacer uso de este método :: para lograr esto. Mi mirada código como este

var outList = List(Nil) 
val strArray = Array("ram","sam","bam") 

for (str<-strArray) 
    outList = str :: outList 

Aunque funciona de alguna manera, el problema es las nuevas cadenas son pre-adjunto en la lista. Pero el requisito ideal es el orden de los datos. Sí, sé lo que estás pensando, puedes revertir la lista de resultados finales para obtener el orden original. Pero el problema es que es una gran variedad. Y creo que no es una solución, aunque resuelve el problema. Creo que debería haber una manera simple de resolver esto ...

Y mi razón para hackear Scala es aprender la forma funcional de la codificación. Tener var (tipo mutable) y poblar la lista sobre la marcha me parece que no es una forma funcional de resolver las cosas.

¿Cómo puedo hacerlo?

Lo ideal es que quiero lograr algo como esto en Scala (por debajo del código de C#)

List<int> ls = new List<int>();  
for (int i = 0; i < 100; i++) 
    ls.Add(i); 

Respuesta

29

Pero parece Scala Arrays & Las listas no proporcionan ningún método para agregar elementos dinámicamente debido a la naturaleza inmutable.

Bueno, no. Scala matrices son sólo arrays de Java, por lo que son mutable:

val arr = Array(1,2) 

arr(0) = 3 // arr == Array(3, 2) 

Pero al igual que Java (y C/C++/C#/etc.) Matrices, no se puede cambiar el tamaño de una matriz .

Así que necesita otra colección, que esté respaldada por una matriz, pero que permita el cambio de tamaño. Una colección adecuada en Scala es scala.collection.mutable.ArrayBuffer, java.util.ArrayList en Java, etc.

Si desea obtener una List en lugar de un Array al final, utilizar scala.collection.mutable.ListBuffer lugar.

+4

gracias .. "ListBuffer" es el que yo quería .. :) – RameshVel

3

bien, hay algunas cosas que aclarar.

Esto está mal, usted es hacer una lista de elementos, que contiene una lista vacía:

scala> var outList = List(Nil) 
outList: List[object Nil] = List(List()) 

Nil es la lista vacía:

scala> var outList: List[String] = Nil 
outList: List[String] = List() 

O, si lo prefiere:

scala> var outList = List[String]() 
outList: List[String] = List() 

Sin más contexto, es difícil saber a qué te refieres con 'dinámico'. El código de ejemplo sería mejor escribir como:

scala> val strArray = Array("ram","sam","bam") 
strArray: Array[java.lang.String] = Array(ram, sam, bam) 

scala> strArray toList 
res0: List[java.lang.String] = List(ram, sam, bam) 

Si desea una colección mutable que puede crecer y eficiente manejar anteponer, añadir, e insertar las operaciones, se puede usar scala.mutable.Buffer.

+1

Agregue formato a los 2 ejemplos en el medio. –

+0

dinámicamente en el sentido "quiero llenar la lista sobre la marcha". el tamaño es desconocido. Podría ser cualquier cosa en función de los datos entrantes ...He actualizado mi pregunta para mayor claridad – RameshVel

3

Va después de la respuesta de retronym:

Si aún desea utilizar la lista hay algunas maneras de anteponer un elemento a la lista. Lo que puede hacer es (sí, la parte superior sigue siendo incorrecta):

scala> var outList : List[String] = Nil 
outList: List[String] = List() 

scala> val strArray = Array("a","b","c") 
strArray: Array[java.lang.String] = Array(a, b, c) 

scala> for(s <- strArray)  
    | outList = outList :+ s 

scala> outList 
res2: List[String] = List(a, b, c) 

Tenga en cuenta el operador: +. Si prefieres anexar, usarás s +: outList.

¿Quién dice que programar en Scala no es divertido? ;)

P.S. Tal vez la razón por la que querrías hacerlos inmutables es la velocidad. Manejar datos grandes será más eficiente con tipos de datos inmutables. ¿Estoy en lo cierto?

+0

Tenga en cuenta que 'for (s <- strArray) {outList = outList: + s}' toma tiempo cuadrático. –

+0

¡Ahh, cabrón! De Verdad? ¿Qué pasa con outList ::: s? ¿Tiene alguna referencia de la complejidad de las funciones scala? Intenté buscar en Google sin encontrar nada. Desde http://stackoverflow.com/questions/1241166/preferred-way-to-create-a-scala-list Creo que el consenso general es preceder y revertir. –

+1

Lo mismo. 'List' es una lista enlazada inmutable, por lo que agregar 1 elemento a uno, cualquiera que sea el método que uses, _hace_ tomar tiempo lineal (ya que tienes que copiar todos sus elementos), por lo que este ciclo toma un tiempo cuadrático. Anexar a 'ListBuffer' y llamar a 'toList' es mejor que anteponer e invertir, pero anteponer e invertir es mucho mejor que agregarlo a una' Lista'. –

4

Si desea utilizar un Buffer mutable, como se menciona el retrónimo. Se ve así:

scala> var outList = scala.collection.mutable.Buffer[String]() 
outList: scala.collection.mutable.Buffer[String] = ArrayBuffer() 

scala> for(str<-strArray) outList += str       

scala> outList 
res10: scala.collection.mutable.ListBuffer[String] = ListBuffer(ram, sam, bam) 

De todos modos, tal vez es mejor que ver directamente las cosas que quiere hacer con el strArray. Por ejemplo:

strArray map(_.toUpperCase) foreach(println) 
4

Si desea trabajar con estructuras inmutables, puede utilizar el método ++:

scala> val orgList = List(1,2,3) 
orgList: List[Int] = List(1, 2, 3) 

scala> val list2Add = List(4,5,6) 
list2Add: List[Int] = List(4, 5, 6) 

scala> val newList = orgList ++ list2Add 
newList: List[Int] = List(1, 2, 3, 4, 5, 6) 

Si usted quiere hacer más trabajo en los elementos que simplemente añadir ellos se puede utilizar funciones de orden superior:

val newList = orgList ++ list2Add.map(_ * 2) 
newList: List[Int] = List(1, 2, 3, 8, 10, 12) 

o con un bucle for:

val newList = orgList ++ {for(x <- list2Add) yield 2*x} 

O bien, podría crear algún bucle recursivo:

def addAll(toList: List[Int], fromList: List[Int]): List[Int] = 
    fromList match { 
    case x :: tail => addAll(2*x :: toList, tail) 
    case Nil => toList 
    } 

val newList = addAll(orgList, list2Add) 

pero en este caso el orden de los elementos añadidos estará en invertido:

List(12, 10, 8, 1, 2, 3) 

Si desea rendimiento cuando se trabaja con listas, es es mejor invertir el resultado que tratar de agregar nuevos elementos al final. Añadiendo elementos al final de una lista es bueno :-) nooot

+0

eso no es requisito ... quiero llenar la lista sobre la marcha ". El tamaño es desconocido. Podría ser cualquier cosa basada en los datos entrantes ... He actualizado mi pregunta para mayor claridad – RameshVel

2

Si usted está buscando para crear una nueva colección, se puede utilizar la palabra clave de rendimiento:

val outlist = for(i <- 0 to 100) yield i 

O:

val arrList = "Some" :: "Input" :: "List" :: Nil 
val outlist = for (i <- arrList) yield i 

Técnicamente, outlist es un Seq en los dos ejemplos anteriores, por lo que puede necesitar llamar al método toList si necesita algunos de los métodos de List.

+1

Ni siquiera necesita decir 'para (i <- 0 a 100) ceder i'. Puede simplemente decir' (0 a 100) 'y, si lo desea, convertirlo a una colección diferente con el método '.toList' o similar. –

Cuestiones relacionadas