Agregar un elemento al final de una lista en Scala

223

Parece una pregunta estúpida, pero todo lo que encontré en Internet fue basura. Simplemente no puedo agregar un elemento de tipo Ten una lista List[T]. Intenté con, myList ::= myElementpero parece que crea un objeto extraño y el acceso a myList.lastsiempre devuelve el primer elemento que se puso dentro de la lista.

Masiar
fuente

Respuestas:

394
List(1,2,3) :+ 4

Results in List[Int] = List(1, 2, 3, 4)

Tenga en cuenta que esta operación tiene una complejidad de O (n). Si necesita esta operación con frecuencia, o para listas largas, considere usar otro tipo de datos (por ejemplo, un ListBuffer).

Landei
fuente
77
No hay O (2 * n), los factores constantes se ignoran para las complejidades asintóticas. Creo que Listse convierte en a ListBuffer, se agrega el elemento y se ListBuffervuelve a convertir (más o menos como Stringy StringBuilderen Java), pero eso es solo una suposición.
Landei
2
Es O (n) porque tiene que recorrer la lista por completo para llegar al último puntero del elemento y poder agregar el elemento haciendo que el último puntero del elemento apunte hacia él.
pisaruk
39
@pisaruk si ese fuera el caso, uno podría simplemente mantener un puntero a la cabeza y la cola. Sin embargo, la lista en scala es inmutable, lo que significa que para "modificar" el último elemento de la lista, primero se necesita hacer una copia. Es la copia que es O (n), no el recorrido de la lista en sí.
2
Creo que es O (n) simplemente porque crea una lista completamente nueva
Raffaele Rossi
3
El operador contra tiene complejidad O (1), ya que funciona en el lado "previsto" de la lista.
Landei
67

Eso es porque no deberías hacerlo (al menos con una lista inmutable). Si realmente necesita agregar un elemento al final de una estructura de datos y esta estructura de datos realmente necesita ser una lista y esta lista realmente tiene que ser inmutable, haga lo siguiente:

(4 :: List(1,2,3).reverse).reverse

o eso:

List(1,2,3) ::: List(4)
agilesteel
fuente
¡Muchas gracias! Eso era exactamente lo que estaba buscando. Sin embargo, supongo que por su respuesta no debería hacer eso ... Revisaré mi estructura y veré qué puedo hacer. Gracias de nuevo.
Masiar
66
@Masiar usa un Vector si quieres inmutabilidad y un agregado eficiente. Consulte la sección de características de rendimiento en scala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl
29
La "creación de la lista precediendo y luego invirtiéndola" es un patrón útil si tiene muchos elementos para agregar, pero no creo que sea una buena idea aplicarla como lo hace en el caso de agregar un solo elemento a un lista existente El truco de "doble inversión" reconstruye la lista dos veces, mientras que :+, por ineficiente que sea, solo la reconstruye una vez.
Nicolas Payette
25

Las listas en Scala no están diseñadas para ser modificadas. De hecho, no puede agregar elementos a una Scala List; Es una estructura de datos inmutable , como una cadena de Java. Lo que realmente hace cuando "agrega un elemento a una lista" en Scala es crear una nueva Lista a partir de una Lista existente . (Fuente)

En lugar de usar listas para tales casos de uso, sugiero usar una ArrayBuffero una ListBuffer. Esas estructuras de datos están diseñadas para tener nuevos elementos agregados.

Finalmente, después de realizar todas sus operaciones, el búfer se puede convertir en una lista. Vea el siguiente ejemplo REPL:

scala> import scala.collection.mutable.ListBuffer
import scala.collection.mutable.ListBuffer

scala> var fruits = new ListBuffer[String]()
fruits: scala.collection.mutable.ListBuffer[String] = ListBuffer()

scala> fruits += "Apple"
res0: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple)

scala> fruits += "Banana"
res1: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple, Banana)

scala> fruits += "Orange"
res2: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple, Banana, Orange)

scala> val fruitsList = fruits.toList
fruitsList: List[String] = List(Apple, Banana, Orange)
Markus Weninger
fuente
3

Esto es similar a una de las respuestas pero de manera diferente:

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

scala> val y=x:::4::Nil
y: List[Int] = List(1, 2, 3, 4)
Venkat
fuente
2

Podemos agregar o anteponer dos listas o lista y matriz
Anexar:

var l = List(1,2,3)    
l=l:+4 
Result : 1 2 3 4  
var ar = Array(4,5,6)    
for(x<-ar)    
{ l=l:+x}  
  l.foreach(println)

Result:1 2 3 4 5 6

Previo:

var l = List[Int]()  
   for(x<-ar)  
    { l=x::l } //prepending    
     l.foreach(println)   

Result:6 5 4 1 2 3
Ramesh Muthavarapu
fuente
1
Sí, podemos, pero sería una mala idea por todas las razones mencionadas en las otras respuestas.
jwvh