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.