webentwicklung-frage-antwort-db.com.de

So erweitern Sie ein vorhandenes JavaScript-Array mit einem anderen Array, ohne ein neues Array zu erstellen

Es scheint keine Möglichkeit zu geben, ein vorhandenes JavaScript-Array um ein anderes Array zu erweitern, d. H. Um die extend-Methode von Python 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 es erstellt ein neues Array, anstatt das erste einfach zu erweitern. Ich möchte einen Algorithmus, der effizient arbeitet, wenn a wesentlich größer als b ist (d. H. Einer, der a nicht kopiert).

Note: Dies ist kein Duplikat von Wie füge ich etwas an ein Array an? - das Ziel ist es, den gesamten Inhalt eines Arrays dem anderen hinzuzufügen "In Place", dh ohne alle Elemente des erweiterten Arrays zu kopieren.

776
DzinX

Die Methode .Push kann mehrere Argumente annehmen. Sie können den Operator spread verwenden, um alle Elemente des zweiten Arrays als Argumente an .Push zu übergeben:

>>> a.Push(...b)

Wenn Ihr Browser ECMAScript 6 nicht unterstützt, können Sie stattdessen .apply verwenden:

>>> a.Push.apply(a, b)

Oder vielleicht, wenn Sie es für klarer halten:

>>> Array.prototype.Push.apply(a,b)

Bitte beachten Sie, dass alle diese Lösungen mit einem Stack-Overflow-Fehler ausfallen, wenn das Array b zu lang ist (der Fehler beginnt bei etwa 100.000 Elementen, abhängig vom Browser). Wenn Sie nicht garantieren können, dass b kurz genug ist, sollten Sie eine Standardschleifenmethode verwenden, die in der anderen Antwort beschrieben wird.

1194
DzinX

Update 2018: Eine bessere Antwort ist eine neuere von mir : a.Push(...b). Stoppen Sie dieses nicht mehr, da es die Frage nie wirklich beantwortet hat, aber es war ein 2015er Hacker um First-Hit-on-Google :)


Für diejenigen, die einfach nach "JavaScript array extend" gesucht haben und hierher gekommen sind, können Sie Array.concat verwenden.

var a = [1, 2, 3];
a = a.concat([5, 4, 3]);

Concat gibt eine Kopie des neuen Arrays zurück, da der Thread-Starter dies nicht wollte. Aber es ist Ihnen vielleicht egal (für die meisten Anwendungen ist dies in Ordnung).


Dazu gibt es in Form des Spread-Operators auch etwas Nice ECMAScript 6-Zucker:

const a = [1, 2, 3];
const b = [...a, 5, 4, 3];

(Es kopiert auch.)

222

Sie sollten eine schleifenbasierte Technik verwenden. Andere Antworten auf dieser Seite, die auf der Verwendung von .apply basieren, können bei großen Arrays fehlschlagen.

Eine ziemlich knappe Loop-basierte Implementierung ist:

Array.prototype.extend = function (other_array) {
    /* You should include a test to check whether other_array really is an array */
    other_array.forEach(function(v) {this.Push(v)}, this);
}

Sie können dann Folgendes tun:

var a = [1,2,3];
var b = [5,4,3];
a.extend(b);

DzinXs Antwort (mit Push.apply) und anderen .apply-basierten Methoden schlagen fehl, wenn das angefügte Array groß ist (Tests zeigen, dass für mich> 150.000 Einträge in Chrome und> 500.000 Einträge in Firefox groß sind). Sie können diesen Fehler in this jsperf sehen.

Ein Fehler tritt auf, weil die Größe des Aufrufstacks überschritten wird, wenn 'Function.prototype.apply' mit einem großen Array als zweitem Argument aufgerufen wird. (Das MDN enthält einen Hinweis zu den Gefahren der Überschreitung der Aufrufstapelgröße bei Verwendung von Function.prototype.apply - siehe Abschnitt "Anwenden und integrierte Funktionen".)

Einen Geschwindigkeitsvergleich mit anderen Antworten auf dieser Seite finden Sie unter this jsperf (Dank an EaterOfCode). Die schleifenbasierte Implementierung ähnelt der Verwendung von Array.Push.apply, ist jedoch etwas langsamer als Array.slice.apply.

Wenn das Array, das Sie anfügen, spärlich ist, kann die oben genannte forEach-Methode die Sparsity vorteilhaft nutzen und die .apply-basierten Methoden übertreffen. check out this jsperf wenn Sie dies selbst testen möchten.

Seien Sie übrigens nicht (wie ich!) In der Versuchung, die forEach-Implementierung weiter zu verkürzen:

Array.prototype.extend = function (array) {
    array.forEach(this.Push, this);
}

denn dies führt zu Müllergebnissen! Warum? Da Array.prototype.forEach der aufgerufenen Funktion drei Argumente zur Verfügung stellt, sind dies: (element_value, element_index, source_array). Alle diese werden bei jeder Iteration von forEach in Ihr erstes Array verschoben, wenn Sie "forEach (this.Push, this)" verwenden!

185
jcdude

Ich fühle mich am elegantesten in diesen Tagen:

arr1.Push(...arr2);

Der MDN-Artikel zum Spread-Operator erwähnt diesen nizza-zuckerhaltigen Weg in ES2015 (ES6):

Ein besserer Push

Beispiel: Push wird häufig verwendet, um ein Array an das Ende eines vorhandenen .__ zu verschieben. Array. In ES5 geschieht dies häufig als:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
Array.prototype.Push.apply(arr1, arr2);

In ES6 mit Spread wird dies zu:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.Push(...arr2);

Beachten Sie, dass arr2 nicht riesig sein kann (halten Sie es unter etwa 100.000 Elementen), da der Aufrufstapel laut Antwort von jcdude überläuft.

142

Zuerst ein paar Worte zu apply() in JavaScript, um zu verstehen, warum wir es verwenden:

Die apply()-Methode ruft eine Funktion mit einem bestimmten this-Wert und .__ auf. Argumente, die als Array bereitgestellt werden.

Push erwartet eine list 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, die Elemente eines Arrays mit der eingebauten Push()-Methode leicht in ein anderes Array zu Push.

Stellen Sie sich vor, Sie haben diese Arrays:

var a = [1, 2, 3, 4];
var b = [5, 6, 7];

und mach einfach das:

Array.prototype.Push.apply(a, b);

Das Ergebnis wird sein:

a = [1, 2, 3, 4, 5, 6, 7];

Das gleiche kann in ES6 mit dem Spread-Operator ("...") wie folgt gemacht werden:

a.Push(...b); //a = [1, 2, 3, 4, 5, 6, 7]; 

Kürzer und besser, aber derzeit nicht in allen Browsern vollständig unterstützt.

Auch wenn Sie alles von Array b zu averschieben und dabei b leeren wollen, können Sie Folgendes tun:

while(b.length) {
  a.Push(b.shift());
} 

und das Ergebnis wird wie folgt sein:

a = [1, 2, 3, 4, 5, 6, 7];
b = [];
46
Alireza

Wenn Sie jQuery verwenden möchten, gibt es $ .merge ()

Beispiel:

a = [1, 2];
b = [3, 4, 5];
$.merge(a,b);

Ergebnis: a = [1, 2, 3, 4, 5]

38
Jules Colle

Ich mag die oben beschriebene a.Push.apply(a, b)-Methode, und wenn Sie möchten, können Sie immer eine Bibliotheksfunktion wie folgt erstellen:

Array.prototype.append = function(array)
{
    this.Push.apply(this, array)
}

und benutze es so

a = [1,2]
b = [3,4]

a.append(b)
18

Es ist möglich, dies mit splice() zu tun:

b.unshift(b.length)
b.unshift(a.length)
Array.prototype.splice.apply(a,b) 
b.shift() // Restore b
b.shift() // 

Obwohl hässlicher ist es nicht schneller als Push.apply, zumindest nicht in Firefox 3.0.

13
Rafał Dowgird

Diese Lösung funktioniert für mich (mit dem Spread-Operator von ECMAScript 6):

let array = ['my', 'solution', 'works'];
let newArray = [];
let newArray2 = [];
newArray.Push(...array); // Adding to same array
newArray2.Push([...array]); // Adding as child/leaf/sub-array
console.log(newArray);
console.log(newArray2);

4

Sie können eine Polyfill für die Erweiterung erstellen, wie ich es unten habe. Es wird dem Array hinzugefügt. In-Place und Return selbst, so dass Sie andere Methoden verketten können.

if (Array.prototype.extend === undefined) {
  Array.prototype.extend = function(other) {
    this.Push.apply(this, arguments.length > 1 ? arguments : other);
    return this;
  };
}

function print() {
  document.body.innerHTML += [].map.call(arguments, function(item) {
    return typeof item === 'object' ? JSON.stringify(item) : item;
  }).join(' ') + '\n';
}
document.body.innerHTML = '';

var a = [1, 2, 3];
var b = [4, 5, 6];

print('Concat');
print('(1)', a.concat(b));
print('(2)', a.concat(b));
print('(3)', a.concat(4, 5, 6));

print('\nExtend');
print('(1)', a.extend(b));
print('(2)', a.extend(b));
print('(3)', a.extend(4, 5, 6));
body {
  font-family: monospace;
  white-space: pre;
}

2
Mr. Polywhirl

Ich kann sehr schöne Antworten sehen, und alles hängt von Ihrer Arraygröße, Ihren Anforderungen und Zielen ab. Dies kann auf verschiedene Arten geschehen.

Ich schlage vor, ein JavaScript für die Schleife zu verwenden:

var a = [1, 2];
var b = [3, 4, 5];

for (i = 0; i < b.length; i++) {
    a.Push(b[i]);
}

console.log(a) wird ausgegeben

Array [ 1, 2, 3, 4, 5 ]

Dann können Sie Ihre eigene Funktion erstellen:

function extendArray(a, b){
    for (i = 0; i < b.length; i++) {
        a.Push(b[i]);
    }
    return a;
}

console.log(extendArray(a, b)); wird ausgegeben

Array [ 1, 2, 3, 4, 5 ]

Verwenden Sie Array.extend anstelle von Array.Push für> 150.000 Datensätze.

if (!Array.prototype.extend) {
  Array.prototype.extend = function(arr) {
    if (!Array.isArray(arr)) {
      return this;
    }

    for (let record of arr) {
      this.Push(record);
    }

    return this;
  };
}
0
Mahdi Pedram

Antworten kombinieren ...

Array.prototype.extend = function(array) {
    if (array.length < 150000) {
        this.Push.apply(this, array)
    } else {
        for (var i = 0, len = array.length; i < len; ++i) {
            this.Push(array[i]);
        };
    }  
}
0
zCoder

Eine weitere Lösung zum Zusammenführen von mehr als zwei Arrays

var a = [1, 2],
    b = [3, 4, 5],
    c = [6, 7];

// Merge the contents of multiple arrays together into the first array
var mergeArrays = function() {
 var i, len = arguments.length;
 if (len > 1) {
  for (i = 1; i < len; i++) {
    arguments[0].Push.apply(arguments[0], arguments[i]);
  }
 }
};

Dann anrufen und ausdrucken als:

mergeArrays(a, b, c);
console.log(a)

Die Ausgabe wird sein: Array [1, 2, 3, 4, 5, 6, 7]

0
user3126309