Aggiunta di un elemento alla fine di un elenco in Scala


223

Sembra una domanda stupida, ma tutto quello che ho trovato su Internet era spazzatura. Semplicemente non riesco ad aggiungere un elemento di tipo Tin un elenco List[T]. Ho provato con, myList ::= myElementma sembra che crei uno strano oggetto e l'accesso a myList.lastrestituisce sempre il primo elemento inserito nell'elenco.

Risposte:


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

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

Si noti che questa operazione ha una complessità di O (n). Se è necessaria questa operazione frequentemente o per elenchi lunghi, considerare l'utilizzo di un altro tipo di dati (ad esempio un ListBuffer).


7
Non c'è O (2 * n), i fattori costanti vengono ignorati per le complessità asintotiche. Credo che la Listviene convertito in un ListBuffer, l'elemento viene aggiunto, e la ListBufferschiena convertito (più o meno come Stringe StringBuilderin Java), ma questo è solo una supposizione.
Landei,

2
È O (n) perché devi attraversare completamente l'elenco per raggiungere l'ultimo puntatore elemento ed essere in grado di aggiungere l'elemento facendo puntare l'ultimo puntatore elemento.
pisaruk,

39
@pisaruk se così fosse, si potrebbe semplicemente mantenere un puntatore alla testa e alla coda. Tuttavia, l' elenco in scala è immutabile, il che significa che per "modificare" l'ultimo elemento dell'elenco è necessario prima crearne una copia. È la copia che è O (n) - non l'attraversamento dell'elenco stesso.

2
Credo che sia O (n) semplicemente perché crea un nuovo elenco
Raffaele Rossi,

3
L'operatore contro ha la complessità O (1), poiché funziona sul lato "previsto" dell'elenco.
Landei,

67

Questo perché non dovresti farlo (almeno con un elenco immutabile). Se hai davvero bisogno di aggiungere un elemento alla fine di una struttura di dati e questa struttura di dati ha davvero bisogno di essere un elenco e questo elenco deve davvero essere immutabile, allora fai questo:

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

o quello:

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

Molte grazie! Era esattamente quello che stavo cercando. Immagino che dalla tua risposta non dovrei farlo però ... Revisionerò la mia struttura e vedrò cosa posso fare. Grazie ancora.
Masiar,

6
@Masiar usa un Vector se vuoi immutabilità e un'aggiunta efficiente. Vedi la sezione delle caratteristiche prestazionali in scala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl,

29
"Costruisci la lista anteponendola e poi invertendola" è un modello utile se hai molti elementi da aggiungere, ma non credo sia una buona idea applicarla come fai tu nel caso di aggiungere un singolo elemento a un elenco esistente. Il trucco del "doppio rovescio" ricostruisce l'elenco due volte, mentre :+, per quanto inefficiente, lo ricostruisce solo una volta.
Nicolas Payette,

25

Gli elenchi in Scala non sono progettati per essere modificati. In effetti, non è possibile aggiungere elementi a una Scala List; è una struttura di dati immutabile , come una stringa Java. Quello che realmente fai quando "aggiungi un elemento a un elenco" in Scala è creare un nuovo Elenco da un Elenco esistente . (Fonte)

Invece di utilizzare elenchi per tali casi d'uso, suggerisco di utilizzare un ArrayBuffero un ListBuffer. Tali strutture dati sono progettate per aggiungere nuovi elementi.

Alla fine, dopo aver completato tutte le operazioni, il buffer può essere convertito in un elenco. Vedi il seguente esempio 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

Questo è simile a una delle risposte ma in modo diverso:

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

Possiamo aggiungere o anteporre due elenchi o aggiungere elenchi e array
:

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

anteponendo:

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

Result:6 5 4 1 2 3

1
Sì, possiamo, ma sarebbe una cattiva idea per tutti i motivi menzionati nelle altre risposte.
jwvh,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.