2009-09-18 20 views
12

Desidero copiare in modo superficiale un elenco in Scala.Come copiare un elenco in Scala

ho voluto fare somehing come:

val myList = List("foo", "bar") 
val myListCopy = myList.clone 

Ma il metodo clone è protetto.

+0

Non sarebbe legato alla http://stackoverflow.com/questions/1267261/does-scala-anyref-clone-perform-a-shallow-or-deep-copy? – VonC

+12

Per cosa? Gli oggetti elenco sono immutabili. –

+1

Volevo rimuovere un elemento dall'elenco (utilizzando il metodo remove (A => Boolean)) in un ciclo. (Nota: ho avviato Scala 2 ore fa :)) – Maxime

risposta

6

per filtrare un elenco:

val list = List(1,2,3,4,5) 
//only evens 
val evens = list.filter(e=>e%2 == 0) 

println(list) 
//--> List(1, 2, 3, 4, 5) 

println(evens) 
//--> List(2, 4) 

è anche possibile utilizzare il carattere jolly per salvare alcuni personaggi:

val evens = list.filter(_%2==0) 

Si noti che, come commentato in precedenza, le liste sono immutabili. Ciò significa che queste operazioni non modificano l'elenco originale, ma in realtà creano un nuovo elenco.

13

Ecco una non risposta: non farlo. Un List è immutabile, quindi non ha assolutamente senso copiarne uno.

Prendiamo in considerazione un paio di operazioni:

val list = List(1,2,3) 
val l1 = 0 :: list 
val l2 = "a" :: list 

l1l2 stanno alterando list, ma entrambi creare nuove liste che fanno riferimento a list.

Spieghiamo questo in dettaglio. Il costruttore List(1,2,3) sta creando tre elementi e utilizza anche un oggetto singleton. In particolare, si istanziare questi elementi:

::(3, Nil) 
::(2, reference to the previous element) 
::(1, reference to the previous element) 

E Nil è un oggetto singoletto. Ciò a cui l'identificatore list punta effettivamente è l'ultimo elemento.

Ora, quando si assegnano 0 :: list-l1, si sta istanziare un nuovo oggetto:

::(0, reference to ::(1, etc)) 

Naturalmente, dato che c'è un riferimento a list, si può pensare di l1 come una lista di quattro elementi (o cinque, se contate Nil).

Ora l2 non è nemmeno dello stesso tipo di list, ma lo fa anche ANCHE! Qui:

::("a", reference to ::(1, etc)) 

Il punto importante di tutti questi oggetti, però, è che essi non possono essere cambiati. Non ci sono setter, né alcun metodo che cambierà nessuna delle loro proprietà. Avranno sempre gli stessi valori/riferimenti nella loro "testa" (questo è ciò che chiamiamo il primo elemento) e gli stessi riferimenti nella loro "coda" (questo è ciò che chiamiamo il secondo elemento).

Tuttavia, ci sono metodi che sembrano come se stessero cambiando la lista. State certi, tuttavia, che stanno creando nuovi elenchi.Per esempio:

val l3 = list map (n => n + 1) 

La mappa metodo crea una nuova lista, delle stesse dimensioni, in cui elemento nuovo può essere calcolata da un elemento corrispondente nella list (ma si potrebbe ignorare il vecchio elemento pure).

val l4 = l2 filter (n => n.isInstanceOf[Int]) 

Mentre l4 ha gli stessi elementi list (ma un tipo diverso), è anche un nuovo elenco. Il metodo filter crea un nuovo elenco, basato su una regola che si passa per dirgli quali elementi vanno e quali no. Non tenta di ottimizzare nel caso in cui potrebbe restituire un elenco esistente.

val l5 = list.tail 

Questo non crea un nuovo elenco. Invece, assegna semplicemente a l5 un elemento esistente di list.

val l6 = list drop 2 

Ancora nessuna nuova lista creata.

val l7 = list take 1 

Questo, tuttavia, crea un nuovo elenco, proprio perché non può cambiare il primo elemento di list in modo che i suoi punti di coda a Nil.

Ecco alcuni ulteriori dettagli di implementazione:

  • List è una classe astratta. Ha due discendenti, la classe :: (sì, questo è il nome della classe) e l'oggetto singleton Nil. List è sigillato, quindi non è possibile aggiungere nuove sottoclassi e :: è definitivo, quindi non è possibile creare una sottoclasse.

  • Mentre non è possibile fare nulla per modificare un elenco, utilizza lo stato mutabile internamente in alcune operazioni. Questo aiuta con le prestazioni, ma è localizzato in modo che nessun programma che scrivi possa mai rilevarlo o subire conseguenze da esso. Puoi passare gli elenchi come preferisci, indipendentemente dalle funzioni che le altre funzioni fanno con loro o da quanti thread li stanno utilizzando contemporaneamente.

Problemi correlati