Scala: qual è il modo migliore per aggiungere un elemento a un Array?


111

Dì che ho un Array[Int]simile

val array = Array( 1, 2, 3 )

Ora vorrei aggiungere un elemento all'array, ad esempio il valore 4, come nell'esempio seguente:

val array2 = array + 4     // will not compile

Ovviamente posso usarlo System.arraycopy()e farlo da solo, ma deve esserci una funzione di libreria Scala per questo, che semplicemente non sono riuscito a trovare. Grazie per eventuali suggerimenti!

Appunti:

  1. Sono consapevole di poter aggiungere un altro Array di elementi, come nella riga seguente, ma sembra troppo rotondo:

    val array2b = array ++ Array( 4 )     // this works
  2. Sono consapevole dei vantaggi e degli svantaggi di List vs Array ed eccomi qui per vari motivi specificamente interessato a estendere un Array.

Modifica 1

Grazie per le risposte che puntano al :+metodo dell'operatore. Questo è quello che stavo cercando. Sfortunatamente, è piuttosto più lento di un'implementazione del metodo append () personalizzato che utilizza arraycopy- circa due o tre volte più lento. Guardando l'implementazione in SeqLike[], viene creato un builder, quindi l'array viene aggiunto ad esso, quindi l'append viene eseguita tramite il builder, quindi viene eseguito il rendering del builder. Non è una buona implementazione per gli array. Ho fatto un rapido benchmark confrontando i due metodi, cercando il tempo più veloce su dieci cicli. L'esecuzione di 10 milioni di ripetizioni di un'appendice di un singolo elemento a un'istanza di matrice a 8 elementi di una classe Foorichiede 3,1 secondi con :+e 1,7 secondi con un append()metodo semplice che utilizzaSystem.arraycopy(); esecuzione di 10 milioni di ripetizioni di accodamento di un singolo elemento su array di 8 elementi di Long richiede 2,1 secondi con :+e 0,78 secondi con il sempliceappend() metodo . Mi chiedo se questo non possa essere risolto nella libreria con un'implementazione personalizzata per Array?

Modifica 2

Per quello che vale, ho presentato un ticket: https://issues.scala-lang.org/browse/SI-5017


11
Perché non usare ArrayBuffere il suo +=metodo? Questo ti darà O (1) append ammortizzato.
Fred Foo,

1
In scala, System.arraycopy(...)è sostituito daArray.copy(...)
paradigmatico

1
Sei consapevole dei vantaggi e degli svantaggi di List vs Array, ma sei sorpreso dei risultati di benchmark di 10 milioni di aggiunte?
utente sconosciuto

Puoi eseguire di nuovo il tuo benchmark usando un ArrayBufferche viene convertito dopo l' ultima aggiunta a un array (con toArray)?
paradigmatico

@paradigmatic: Il benchmark ovviamente non era di 10 milioni di aggiunte allo stesso array ma 10 milioni di ripetizioni di un singolo elemento aggiunto a un array di 8 elementi. Ho aggiornato la domanda di conseguenza.
Gregor Scheidt

Risposte:


204

Puoi usare :+per aggiungere un elemento all'array e +:per anteporlo:

0 +: array :+ 4

dovrebbe produrre:

res3: Array[Int] = Array(0, 1, 2, 3, 4)

È lo stesso di qualsiasi altra implementazione di Seq.


3
È lo stesso per qualsiasi altra raccolta ordinata su scala , ad esempio non funziona con set (poiché anteponi e aggiungi non significano nulla per un Set).
Nicolas

@Nicolas Qualsiasi sequenza. Ordinato implica ordinato .
Daniel C. Sobral,

@Daniel Sì, ho solo un piccolo buco nella memoria quando ho scritto il commento e non ho trovato la parola ovvia "sequenza"
Nicolas

@tenshi tutti questi operatori creerebbero un nuovo array? Sì, lo fa (da: + codice)Array.copy(repr, 0, result, 0, repr.length)
Timofey

59
val array2 = array :+ 4
//Array(1, 2, 3, 4)

Funziona anche "al contrario":

val array2 = 4 +: array
Array(4, 1, 2, 3)

C'è anche una versione "sul posto":

var array = Array( 1, 2, 3 )
array +:= 4
//Array(4, 1, 2, 3)
array :+= 0
//Array(4, 1, 2, 3, 0)

11
Mi chiedo solo perché la raccolta Array non utilizzi il metodo append (), proprio come ArrayBuffer. Secondo me, è più coordinamento e unificazione che usare un nuovo operatore: + / +:
Djvu

8

Il più semplice potrebbe essere:

Array(1, 2, 3) :+ 4

In realtà, Array può essere implcitamente trasformato in un file WrappedArray


In tal caso, sarebbe la conversione con priorità più alta a ArrayOps
Didier Dupont,
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.