Scala: Wie kann ein Element am besten an ein Array angehängt werden?


111

Sagen wir, ich habe ein Array[Int]Like

val array = Array( 1, 2, 3 )

Jetzt möchte ich ein Element an das Array anhängen 4, beispielsweise den Wert , wie im folgenden Beispiel:

val array2 = array + 4     // will not compile

Ich kann das natürlich System.arraycopy()alleine benutzen und tun, aber dafür muss es eine Scala-Bibliotheksfunktion geben, die ich einfach nicht finden konnte. Vielen Dank für Hinweise!

Anmerkungen:

  1. Mir ist bewusst, dass ich ein weiteres Array von Elementen anhängen kann, wie in der folgenden Zeile, aber das scheint zu rund:

    val array2b = array ++ Array( 4 )     // this works
  2. Ich bin mir der Vor- und Nachteile von List vs Array bewusst und bin aus verschiedenen Gründen speziell an der Erweiterung eines Arrays interessiert.

Bearbeiten 1

Vielen Dank für die Antworten auf die :+Operatormethode. Das habe ich gesucht. Leider ist es eher langsamer als die Implementierung einer benutzerdefinierten append () -Methode arraycopy- etwa zwei- bis dreimal langsamer. Wenn Sie sich die Implementierung in ansehen SeqLike[], wird ein Builder erstellt, das Array hinzugefügt, das Anhängen über den Builder ausgeführt und der Builder gerendert. Keine gute Implementierung für Arrays. Ich habe einen schnellen Benchmark durchgeführt, bei dem die beiden Methoden verglichen wurden, wobei die schnellste Zeit aus zehn Zyklen betrachtet wurde. Das Ausführen von 10 Millionen Wiederholungen eines einzelnen Elements, das an eine Array-Instanz mit 8 Elementen einer Klasse Fooangehängt wird, dauert :+mit einer einfachen append()Methode 3,1 Sekunden und mit einer einfachen Methode 1,7 SekundenSystem.arraycopy();Das Ausführen von 10 Millionen Wiederholungen zum Anhängen einzelner Elemente auf 8-Element-Arrays von Long dauert :+mit der einfachen append()Methode 2,1 Sekunden und 0,78 Sekunden . Frage mich, ob dies nicht in der Bibliothek mit einer benutzerdefinierten Implementierung für behoben werden konnte Array?

Bearbeiten 2

Für das, was es wert ist, habe ich ein Ticket eingereicht: https://issues.scala-lang.org/browse/SI-5017


11
Warum nicht verwenden ArrayBufferund seine +=Methode? Dadurch erhalten Sie amortisierte O (1) -Anhänge.
Fred Foo

1
In Scala System.arraycopy(...)wird ersetzt durchArray.copy(...)
paradigmatische

1
Sie sind sich der Vor- und Nachteile von List vs Array bewusst, sind aber von den Benchmark-Ergebnissen von 10 Millionen Anhängen überrascht?
Benutzer unbekannt

Können Sie Ihren Benchmark erneut mit einem ausführen, ArrayBufferder nach dem letzten Anhängen an ein Array (mit toArray) konvertiert wird ?
Paradigmatischer

@paradigmatic: Der Benchmark war natürlich nicht 10 Millionen Anhänge an dasselbe Array, sondern 10 Millionen Wiederholungen eines einzelnen Elements, das an ein 8-Elemente-Array angehängt wurde. Ich habe die Frage entsprechend aktualisiert.
Gregor Scheidt

Antworten:


204

Sie können das :+Element an ein Array anhängen und +:es voranstellen:

0 +: array :+ 4

sollte produzieren:

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

Es ist das gleiche wie bei jeder anderen Implementierung von Seq.


3
Dies gilt auch für alle anderen von Scala bestellten Sammlungen. Es funktioniert beispielsweise nicht mit Sets (da das Voranstellen und Anhängen für ein Set nichts bedeutet).
Nicolas

@Nicolas Beliebige Reihenfolge. Bestellt impliziert sortiert .
Daniel C. Sobral

@ Daniel Ja, ich habe gerade ein kleines Gedächtnisloch, als ich den Kommentar schrieb und ich fand das offensichtliche Wort "Sequenz" nicht
Nicolas

@tenshi würden alle diese Operatoren ein neues Array erstellen? Ja, das tut es (von: + Code)Array.copy(repr, 0, result, 0, repr.length)
Timofey

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

Funktioniert auch "umgekehrt":

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

Es gibt auch eine "In-Place" -Version:

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

11
Ich frage mich nur, warum die Array-Sammlung nicht die append () -Methode verwendet, sondern nur den ArrayBuffer. Meiner Meinung nach ist es mehr Koordination und Vereinheitlichung als die Verwendung eines neuen Operators: + / +:
Djvu

8

Das einfachste könnte sein:

Array(1, 2, 3) :+ 4

Tatsächlich kann Array implizit in a transformiert werden WrappedArray


In diesem Fall wäre dies die Konvertierung mit höherer Priorität in ArrayOps
Didier Dupont
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.