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.

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).


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)

¡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)

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)

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

1
Sí, podemos, pero sería una mala idea por todas las razones mencionadas en las otras respuestas.
jwvh
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.