Es scheint keine Möglichkeit zu geben, ein vorhandenes JavaScript-Array um ein anderes Array zu erweitern, dh die Python- extend
Methode zu emulieren .
Ich möchte Folgendes erreichen:
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]
Ich weiß, dass es eine a.concat(b)
Methode gibt, aber sie erstellt ein neues Array, anstatt einfach das erste zu erweitern. Ich möchte einen Algorithmus, der effizient funktioniert, wenn er a
wesentlich größer ist als b
(dh einer, der nicht kopiert a
).
Hinweis: Dies ist kein Duplikat von Wie man etwas an ein Array anfügt? - Das Ziel hier ist es, den gesamten Inhalt eines Arrays zum anderen hinzuzufügen und dies "an Ort und Stelle" zu tun, dh ohne alle Elemente des erweiterten Arrays zu kopieren.
javascript
arrays
concatenation
DzinX
quelle
quelle
a.push(...b)
. Das Konzept ähnelt der Top-Antwort, wurde jedoch für ES6 aktualisiert.Antworten:
Die
.push
Methode kann mehrere Argumente annehmen. Mit dem Spread-Operator können Sie alle Elemente des zweiten Arrays als Argumente an Folgendes übergeben.push
:Wenn Ihr Browser ECMAScript 6 nicht unterstützt, können Sie
.apply
stattdessen Folgendes verwenden :Oder vielleicht, wenn Sie denken, dass es klarer ist:
Bitte beachten Sie, dass alle diese Lösungen mit einem Stapelüberlauffehler fehlschlagen, wenn das Array
b
zu lang ist (Probleme beginnen je nach Browser bei etwa 100.000 Elementen).Wenn Sie nicht garantieren können, dass dies
b
kurz genug ist, sollten Sie eine in der anderen Antwort beschriebene standardmäßige schleifenbasierte Technik verwenden.quelle
push
Methode kann eine beliebige Anzahl von Argumenten annehmen, die dann an die Rückseite des Arrays verschoben werden . Diesa.push('x', 'y', 'z')
gilt auch für einen gültigen Aufruf, der uma
3 Elemente erweitert wird.apply
ist eine Methode für jede Funktion, die ein Array verwendet und seine Elemente so verwendet, als ob sie alle explizit als Positionselemente für die Funktion angegeben würden. Soa.push.apply(a, ['x', 'y', 'z'])
erstrecken würde auch die Anordnung von 3 Elementen. Nimmt zusätzlichapply
einen Kontext als erstes Argument (wir übergeben ihn dorta
erneut, um ihn anzuhängena
).[].push.apply(a, b)
.Update 2018 : Eine bessere Antwort ist eine neuere von mir :
a.push(...b)
. Stimmen Sie diesem nicht mehr zu, da es die Frage nie wirklich beantwortet hat, aber es war ein Hack von 2015 um den ersten Treffer bei Google :)Für diejenigen, die einfach nach "JavaScript Array Extend" gesucht haben und hierher gekommen sind, können Sie sehr gut verwenden
Array.concat
.Concat gibt eine Kopie des neuen Arrays zurück, da der Thread-Starter dies nicht wollte. Aber es könnte Sie nicht interessieren (sicherlich für die meisten Arten von Anwendungen wird dies in Ordnung sein).
Es gibt auch einige nette ECMAScript 6-Zucker in Form des Spread-Operators:
(Es kopiert auch.)
quelle
arr.push(...arr2)
neuere und bessere und eine technisch korrekte (tm) Antwort auf diese spezielle Frage ist.Sie sollten eine schleifenbasierte Technik verwenden. Andere Antworten auf dieser Seite, die auf der Verwendung basieren,
.apply
können für große Arrays fehlschlagen.Eine ziemlich knappe schleifenbasierte Implementierung ist:
Sie können dann Folgendes tun:
Die Antwort von DzinX (mit push.apply) und andere
.apply
basierte Methoden schlagen fehl, wenn das Array, das wir anhängen, groß ist (Tests zeigen, dass für mich ungefähr 150.000 Einträge in Chrome und> 500.000 Einträge in Firefox groß sind). Sie können diesen Fehler in diesem jsperf sehen .Ein Fehler tritt auf, weil die Größe des Aufrufstapels überschritten wird, wenn 'Function.prototype.apply' mit einem großen Array als zweitem Argument aufgerufen wird. (MDN hat einen Hinweis zu den Gefahren einer Überschreitung der Aufrufstapelgröße mithilfe von Function.prototype.apply - siehe Abschnitt "Anwenden und integrierte Funktionen".)
Einen Geschwindigkeitsvergleich mit anderen Antworten auf dieser Seite finden Sie in diesem jsperf (dank EaterOfCode). Die schleifenbasierte Implementierung ähnelt in ihrer Geschwindigkeit der Verwendung
Array.push.apply
, ist jedoch tendenziell etwas langsamer alsArray.slice.apply
.Interessanterweise
forEach
kann die oben beschriebene Methode die Sparsamkeit ausnutzen und die.apply
basierten Methoden übertreffen , wenn das Array, das Sie anhängen, spärlich ist . Schauen Sie sich dieses jsperf an, wenn Sie dies selbst testen möchten.Übrigens, seien Sie nicht versucht (wie ich!), Die forEach-Implementierung weiter zu verkürzen auf:
weil dies zu Müll führt! Warum? Da
Array.prototype.forEach
die aufgerufene Funktion drei Argumente enthält: (element_value, element_index, source_array). All dies wird bei jeder Iteration auf Ihr erstes Array übertragen,forEach
wenn Sie "forEach (this.push, this)" verwenden!quelle
.push.apply
ist eigentlich viel schneller als.forEach
in v8, die schnellste ist immer noch eine Inline-Schleife..forEach
schneller als.push.apply
in Chrome / Chromium (in allen Versionen seit Version 25). Ich konnte v8 nicht isoliert testen, aber wenn ja, verknüpfen Sie bitte Ihre Ergebnisse. Siehe jsperf: jsperf.com/array-extending-push-vs-concat/5undefined
, so.forEach
werden sie überspringen, es ist die schnellste machen..splice
ist eigentlich der schnellste?! jsperf.com/array-extending-push-vs-concat/18Ich fühle mich heutzutage am elegantesten:
Der MDN-Artikel über den Spread-Operator erwähnt diesen schönen zuckerhaltigen Weg in ES2015 (ES6):
Beachten Sie, dass
arr2
dies nicht sehr groß sein kann (halten Sie es unter etwa 100 000 Elementen), da der Aufrufstapel gemäß der Antwort von jcdude überläuft.quelle
arr1.push(arr2)
. Dies kann ein Problem sein, so dassarr1 = []; arr2=['a', 'b', 'd']; arr1.push(arr2)
das Ergebnis ein Array von Arrays istarr1 == [['a','b','d']]
und nicht zwei Arrays zusammen. Es ist leicht, einen Fehler zu machen. Aus diesem Grund bevorzuge ich Ihre zweite Antwort unten. stackoverflow.com/a/31521404/4808079.concat
ist es praktisch, dass das zweite Argument kein Array sein darf. Dies kann mit durch die Kombination von Spread - Operator erreicht werdenconcat
, zBarr1.push(...[].concat(arrayOrSingleItem))
Zuerst ein paar Worte zu
apply()
JavaScript, um zu verstehen, warum wir es verwenden:Push erwartet eine Liste von Elementen, die dem Array hinzugefügt werden sollen. Die
apply()
Methode verwendet jedoch die erwarteten Argumente für den Funktionsaufruf als Array. Dies ermöglicht es uns,push
die Elemente eines Arrays mit der eingebautenpush()
Methode einfach in ein anderes Array zu verschieben .Stellen Sie sich vor, Sie haben diese Arrays:
und mach das einfach:
Das Ergebnis wird sein:
Dasselbe kann in ES6 mit dem Spread-Operator ("
...
") wie folgt gemacht werden:Kürzer und besser, aber derzeit nicht in allen Browsern vollständig unterstützt.
Auch wenn Sie wollen bewegen alles von Array
b
zua
, Entleerungb
in den Prozess, können Sie dies tun:und das Ergebnis wird wie folgt sein:
quelle
while (b.length) { a.push(b.shift()); }
, richtig?Wenn Sie jQuery verwenden möchten, gibt es $ .merge ()
Beispiel:
Ergebnis: a =
[1, 2, 3, 4, 5]
quelle
jQuery.merge()
?Ich mag die
a.push.apply(a, b)
oben beschriebene Methode, und wenn Sie möchten, können Sie immer eine Bibliotheksfunktion wie folgt erstellen:und benutze es so
quelle
Es ist möglich, dies zu tun mit
splice()
:Aber obwohl es hässlicher ist, ist es nicht schneller als
push.apply
, zumindest nicht in Firefox 3.0.quelle
Diese Lösung funktioniert für mich (mit dem Spread-Operator von ECMAScript 6):
quelle
Sie können eine Polyfüllung zum Erweitern erstellen, wie unten beschrieben. Es wird dem Array hinzugefügt. an Ort und Stelle und geben Sie sich zurück, so dass Sie andere Methoden verketten können.
quelle
Die Antworten kombinieren ...
quelle
Eine weitere Lösung zum Zusammenführen von mehr als zwei Arrays
Rufen Sie dann an und drucken Sie als:
Ausgabe wird sein:
Array [1, 2, 3, 4, 5, 6, 7]
quelle
Die Antwort ist super einfach.
Concat verhält sich sehr ähnlich wie die Verkettung von JavaScript-Zeichenfolgen. Es wird eine Kombination der Parameter zurückgegeben, die Sie in die concat-Funktion am Ende des Arrays eingegeben haben, für das Sie die Funktion aufrufen. Der springende Punkt ist, dass Sie den zurückgegebenen Wert einer Variablen zuweisen müssen, sonst geht er verloren. So zum Beispiel
quelle
Array.prototype.concat()
bei MDN klar angegeben, wird ein neues Array zurückgegeben , es wird nicht an das vorhandene Array angehängt, wie OP eindeutig gefragt hat.Verwenden Sie
Array.extend
stattArray.push
für> 150.000 Datensätze.quelle
Super einfach, zählt nicht auf Spread-Operatoren oder gilt, wenn das ein Problem ist.
Nach einigen Leistungstests ist dies furchtbar langsam, beantwortet jedoch die Frage, ob kein neues Array erstellt werden soll. Concat ist deutlich schneller, selbst jQuery
$.merge()
macht es klar.https://jsperf.com/merge-arrays19b/1
quelle
.forEach
anstatt ihn zu verwenden.map
. Es vermittelt besser die Absicht Ihres Codes..map
aber Sie könnten auch tunb.forEach(function(x) { a.push(x)} )
. Tatsächlich habe ich das zum jsperf-Test hinzugefügt und es ist ein Haar schneller als die Karte. Immer noch super langsam..map
sieht sehr komisch aus. Es wäre wie ein Anrufb.filter(x => a.push(x))
. Es funktioniert, aber es verwirrt den Leser, indem es impliziert, dass etwas passiert, wenn es nicht passiert..map()
macht und das ist das Problem. Dieses Wissen würde mich denken lassen, dass Sie das resultierende Array benötigen, andernfalls wäre es eine gute Sache.forEach()
, den Leser über die Nebenwirkungen der Rückruffunktion vorsichtig zu machen. Genau genommen erstellt Ihre Lösung ein zusätzliches Array natürlicher Zahlen (Ergebnisse vonpush
), während die Frage lautet: "Ohne ein neues Array zu erstellen".