wake-up-neo.com

Schieben Sie Array-Elemente in ein anderes Array

Ich habe ein JavaScript-Array dataArray, das ich in ein neues Array newArray verschieben möchte. Außer, ich möchte nicht, dass newArray[0]dataArray ist. Ich möchte alle Elemente in das neue Array einschieben:

var newArray = [];

newArray.pushValues(dataArray1);
newArray.pushValues(dataArray2);
// ...

oder noch besser:

var newArray = new Array (
   dataArray1.values(),
   dataArray2.values(),
   // ... where values() (or something equivalent) would Push the individual values into the array, rather than the array itself
);

Das neue Array enthält also alle Werte der einzelnen Datenarrays. Gibt es eine Abkürzung wie pushValues, so dass ich nicht jede einzelne dataArray durchlaufen muss und die Elemente einzeln hinzufügen muss?

741
bba

Verwenden Sie die Funktion concat wie folgt:

var arrayA = [1, 2];
var arrayB = [3, 4];
var newArray = arrayA.concat(arrayB);

Der Wert von newArray ist [1, 2, 3, 4] (arrayA und arrayB bleiben unverändert; concat erstellt ein neues Array für das Ergebnis und gibt es zurück).

1004
WiseGuyEh

Wenn Ihre Arrays nicht sehr groß sind (siehe unten), können Sie die Push()-Methode des Arrays verwenden, an das Sie Werte anhängen möchten. Push() kann mehrere Parameter annehmen, sodass Sie die apply()-Methode verwenden können, um das Array von Werten zu übergeben, die als Liste von Funktionsparametern gepusht werden sollen. Dies hat gegenüber der Verwendung von concat() den Vorteil, dass Elemente zu dem Array hinzugefügt werden, anstatt ein neues Array zu erstellen.

Es scheint jedoch, dass dieser Trick für große Arrays (in der Größenordnung von 100.000 Mitgliedern oder mehr) fehlschlagen kann. Für solche Arrays ist die Verwendung einer Schleife ein besserer Ansatz. Weitere Informationen finden Sie unter https://stackoverflow.com/a/17368101/96100 .

var newArray = [];
newArray.Push.apply(newArray, dataArray1);
newArray.Push.apply(newArray, dataArray2);

Sie können dies in eine Funktion verallgemeinern:

function pushArray(arr, arr2) {
    arr.Push.apply(arr, arr2);
}

... oder fügen Sie es dem Prototyp von Array hinzu:

Array.prototype.pushArray = function(arr) {
    this.Push.apply(this, arr);
};

var newArray = [];
newArray.pushArray(dataArray1);
newArray.pushArray(dataArray2);

... oder emulieren Sie die ursprüngliche Push()-Methode, indem Sie mehrere Parameter zulassen und dabei die Tatsache verwenden, dass concat(), wie Push(), mehrere Parameter zulässt:

Array.prototype.pushArray = function() {
    this.Push.apply(this, this.concat.apply([], arguments));
};

var newArray = [];
newArray.pushArray(dataArray1, dataArray2);

Hier ist eine schleifenbasierte Version des letzten Beispiels, die für große Arrays und alle gängigen Browser geeignet ist, einschließlich IE <= 8:

Array.prototype.pushArray = function() {
    var toPush = this.concat.apply([], arguments);
    for (var i = 0, len = toPush.length; i < len; ++i) {
        this.Push(toPush[i]);
    }
};
608
Tim Down

Ich werde noch eine "zukunftssichere" Antwort hinzufügen

In ECMAScript 6 können Sie den Operator spread verwenden :

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

Der Spread-Operator ist noch nicht in allen gängigen Browsern enthalten. Informationen zur aktuellen Kompatibilität finden Sie in dieser (ständig aktualisierten) Kompatibilitätstabelle

Sie können jedoch den Spread-Operator mit Babel.js verwenden.

bearbeiten:

Siehe unten die Antwort von Jack Giffin für weitere Kommentare zur Leistung. Es scheint, Concat ist immer noch besser und schneller als Spread-Operator.

297
Karel Bílek

Einen eleganten Weg gefunden aus MDN

var vegetables = ['parsnip', 'potato'];
var moreVegs = ['celery', 'beetroot'];

// Merge the second array into the first one
// Equivalent to vegetables.Push('celery', 'beetroot');
Array.prototype.Push.apply(vegetables, moreVegs);

console.log(vegetables); // ['parsnip', 'potato', 'celery', 'beetroot']

Oder Sie können die spread operator-Funktion von ES6 verwenden:

let fruits = [ 'Apple', 'banana'];
const moreFruits = [ 'orange', 'Plum' ];

fruits.Push(...moreFruits); // ["Apple", "banana", "orange", "Plum"]
136
Believe2014
var a=new Array('a','b','c');
var b=new Array('d','e','f');
var d=new Array('x','y','z');
var c=a.concat(b,d)

Löst das dein Problem?

12

Folgendes scheint mir am einfachsten:

var newArray = dataArray1.slice();
newArray.Push.apply(newArray, dataArray2);

Da "Push" eine variable Anzahl von Argumenten benötigt, können Sie die apply-Methode der Push-Funktion verwenden, um alle Elemente eines anderen Arrays zu pushen. Es konstruiert einen Aufruf von Push mit dem ersten Argument ("newArray" hier) als "this" und den Elementen des Arrays als verbleibende Argumente.

Die Variable slice in der ersten Anweisung erhält eine Kopie des ersten Arrays, sodass Sie sie nicht ändern.

Update Wenn Sie eine Version von Javascript mit verfügbarem Slice verwenden, können Sie den Ausdruck Push folgendermaßen vereinfachen:

newArray.Push(...dataArray2)
12
shaunc

Es gibt eine Reihe von Antworten, die über Array.prototype.Push.apply sprechen. Hier ist ein klares Beispiel:

var dataArray1 = [1, 2];
var dataArray2 = [3, 4, 5];
var newArray = [ ];
Array.prototype.Push.apply(newArray, dataArray1); // newArray = [1, 2]
Array.prototype.Push.apply(newArray, dataArray2); // newArray = [1, 2, 3, 4, 5]
console.log(JSON.stringify(newArray)); // Outputs: [1, 2, 3, 4, 5]

Wenn Sie eine ES6-Syntax haben:

var dataArray1 = [1, 2];
var dataArray2 = [3, 4, 5];
var newArray = [ ];
newArray.Push(...dataArray1); // newArray = [1, 2]
newArray.Push(...dataArray2); // newArray = [1, 2, 3, 4, 5]
console.log(JSON.stringify(newArray)); // Outputs: [1, 2, 3, 4, 5]

9
Stephen Quan

Mit JavaScript ES6 können Sie den Operator ... als Spread-Operator verwenden, der das Array im Wesentlichen in Werte konvertiert. Dann können Sie so etwas tun:

const myArray = [1,2,3,4,5];
const moreData = [6,7,8,9,10];

const newArray = [
  ...myArray,
  ...moreData,
];

Obwohl die Syntax kurz ist, weiß ich nicht, wie dies intern funktioniert und welche Auswirkungen auf die Leistung auf große Arrays haben.

7
Ryan H.

Die folgende Funktion hat kein Problem mit der Länge von Arrays und ist besser als alle vorgeschlagenen Lösungen:

function pushArray(list, other) {
    var len = other.length;
    var start = list.length;
    list.length = start + len;
    for (var i = 0; i < len; i++ , start++) {
        list[start] = other[i];
    }
}

leider lehnt es jspref ab, meine eingaben zu akzeptieren. hier sind sie die ergebnisse mit benchmark.js

        Name            |   ops/sec   |  ± %  | runs sampled
for loop and Push       |      177506 |  0.92 | 63
Push Apply              |      234280 |  0.77 | 66
spread operator         |      259725 |  0.40 | 67
set length and for loop |      284223 |  0.41 | 66

woher

für Schleife und Push ist:

    for (var i = 0, l = source.length; i < l; i++) {
        target.Push(source[i]);
    }

Drücken Sie Anwenden:

target.Push.apply(target, source);

spread-Operator:

    target.Push(...source);

und schließlich ist 'set length and for loop' die obige Funktion

7
Panos Theof

????????????????????????????? ???????????? ??????????????????????????

Für die Fakten werden ein Leistungstest bei jsperf und einige Dinge in der Konsole überprüft. Für die Recherche wird die Website irt.org verwendet. Im Folgenden finden Sie eine Sammlung all dieser Quellen sowie eine Beispielfunktion im unteren Bereich.

╔═══════════════╦══════╦═════════════════╦════════ ═══════╦═════════╦══════════╗ 
 ║ Methode ║Concat║slice & Push.apply ║ Push.apply x2 ║ ForLoop ║ Spread ║ 
 ╠═══════════════╬══════╬═════════════════╬═ ══════════════╬═════════╬══════════╣ 
 ║ mOps/Sek. ║179 ║104 ║ 76 ║ 81 ║ 28 ║ 
 ╠═══════════════╬══════╬═══════════════ ══╬═══════════════╬═════════╬══════════╣ 
 ║ Sparse Arrays ║JA ! "Nur das in Scheiben geschnittene Nein. Vielleicht2    ║keine ║ 
 ║ wird spärlich gehalten ║ Array (1. Argument) ║ ║ ║ ║ 
 ╠═══════════════╬══════ ╬═════════════════╬═══════════════╬═════════╬═════ ═════╣ 
 ║ Unterstützung ║MSIE 4║MSIE 5.5 ║ MSIE 5.5 ║ MSIE 4 ║Edge 12 ║ 
 ║ ( source ) ║NNav 4║NNav 4,06 ║ NNav 4,06 ║ NNav 3 ║MSIENNav ║ 
 ╠═══════════════╬══════╬═════════════════╬══ ═════════════╬═════════╬══════════╣ 
 ║Array-artige Handlungen║nur die gedrückt ║ JA! ║ JA! ║Wenn have 
 ║ wie ein Array ║ ║array (2. Argument) ║ ║ ║iterator ist1   ║ 
 ╚═══════════════╩══════╩═════════════════╩══ ═════════════╩═════════╩══════════╝ 
1 Wenn das arrayähnliche Objekt kein Symbol.iterator Wenn Sie dann versuchen, 
 zu verbreiten, wird eine Ausnahme ausgelöst. 
2 Kommt auf den Code an. Der folgende Beispielcode "YES" bewahrt die Sparseness.
function mergeCopyTogether(inputOne, inputTwo){
   var oneLen = inputOne.length, twoLen = inputTwo.length;
   var newArr = [], newLen = newArr.length = oneLen + twoLen;
   for (var i=0, tmp=inputOne[0]; i !== oneLen; ++i) {
        tmp = inputOne[i];
        if (tmp !== undefined || inputOne.hasOwnProperty(i)) newArr[i] = tmp;
    }
    for (var two=0; i !== newLen; ++i, ++two) {
        tmp = inputTwo[two];
        if (tmp !== undefined || inputTwo.hasOwnProperty(two)) newArr[i] = tmp;
    }
    return newArr;
}

Wie oben gezeigt, würde ich argumentieren, dass Concat fast immer der richtige Weg ist, um sowohl Leistung als auch die Fähigkeit zu erreichen, die Kargheit von Ersatz-Arrays beizubehalten. Dann würde ich für Array-Likes (wie DOMNodeLists wie document.body.children) Empfehlen, die for-Schleife zu verwenden, da sie sowohl die zweitperformanteste als auch die einzige andere Methode ist, die spärliche Arrays beibehält. Im Folgenden werden wir kurz darauf eingehen, was mit spärlichen Arrays und Array-Likes gemeint ist, um Verwirrung zu beseitigen.

???????????? ???????????????????????

Auf den ersten Blick könnte man meinen, dass dies ein Zufall ist und dass die Browser-Anbieter irgendwann versuchen werden, Array.prototype.Push so zu optimieren, dass es schnell genug ist, um Array.prototype.concat zu schlagen. FALSCH! Array.prototype.concat ist (zumindest im Prinzip) immer schneller, da es ein einfaches Kopieren und Einfügen der Daten ist. Im Folgenden finden Sie ein vereinfachtes, überzeugend visuelles Diagramm, wie eine 32-Bit-Array-Implementierung aussehen könnte (beachten Sie, dass echte Implementierungen VIEL komplizierter sind)

Byte ║ Daten hier 
 ═════╬═══════════ 
 0x00 ║ int nonNumericPropertiesLength = 0x00000000 
 0x01 ║ ibid 
 0x02 ║ ibid 
 0x03 ║ ibid 
 0x00 ║ int length = 0x00000001 
 0x01 ║ ibid 
 0x02 ║ ibid 
 0x03 ║ ibid 
 0x00 ║ int valueIndex = 0x00000000 
 0x01 ║ ibid 
 0x02 ║ ibid 
 0x03 ║ ibid 
 0x00 ║ int valueType = JS_PRIMITIVE_NUMBER 
 0x01 ║ ibid 
 0x02 ║ ibid 
 0x03 ║ ibid 
 0x00 ║ uintptr_t valuePointer = 0x38d9eb60 (oder wo immer es sich im Speicher befindet) 
 0x01 ║ ibid 
 0x02 ║ ibid 
 0x03 ║ ibid

Wie oben gezeigt, ist alles, was Sie tun müssen, um so etwas zu kopieren, fast so einfach, wie es Byte für Byte zu kopieren. Mit Array.prototype.Push.apply ist es viel mehr als ein einfaches Kopieren und Einfügen der Daten. ".Apply" muss jeden Index im Array überprüfen und in eine Reihe von Argumenten konvertieren, bevor er an Array.prototype.Push übergeben wird. Dann muss Array.prototype.Push zusätzlich jedes Mal mehr Speicher zuweisen und (für einige Browserimplementierungen) möglicherweise sogar einige Positionssuchdaten neu berechnen, um sie auf ihre Sparsamkeit hin zu überprüfen.

Eine alternative Denkweise ist dies. Das erste Quellenarray besteht aus einem großen Stapel zusammengehefteter Papiere. Das Quellenarray zwei ist ebenfalls ein weiterer großer Stapel von Papieren. Wäre es für dich schneller

  1. Gehen Sie in den Laden und kaufen Sie ausreichend Papier für eine Kopie jedes Quell-Arrays. Führen Sie dann die Papierstapel jedes Quell-Arrays durch ein Kopiergerät und heften Sie die resultierenden zwei Kopien zusammen.
  2. Gehen Sie in den Laden und kaufen Sie genügend Papier für eine einzelne Kopie des ersten Quell-Arrays. Kopieren Sie dann das Quell-Array von Hand auf das neue Papier, und achten Sie darauf, dass keine leeren Stellen vorhanden sind. Gehen Sie dann zurück in den Laden und kaufen Sie genügend Papier für das zweite Quell-Array. Gehen Sie dann das zweite Quell-Array durch und kopieren Sie es, wobei Sie darauf achten, dass die Kopie keine Lücken enthält. Heften Sie dann alle kopierten Papiere zusammen.

In der obigen Analogie steht Option 1 für Array.prototype.concat, während Option 2 für Array.prototype.Push.apply steht. Lassen Sie uns dies mit einem ähnlichen JSperf testen, der sich nur darin unterscheidet, dass dieser die Methoden über spärliche Arrays und nicht über solide Arrays testet. Man kann es finden genau hier .

Daher möchte ich mich darauf beschränken, dass die Zukunft der Leistung für diesen speziellen Anwendungsfall nicht in Array.prototype.Push, sondern in Array.prototype.concat liegt.

?????????????????????????????????????????? ??????

??????????????????? ???????????????????????

Wenn bestimmte Mitglieder des Arrays einfach fehlen. Zum Beispiel:

// This is just as an example. In actual code, 
// do not mix different types like this.
var mySparseArray = [];
mySparseArray[0] = "foo";
mySparseArray[10] = undefined;
mySparseArray[11] = {};
mySparseArray[12] =  10;
mySparseArray[17] = "bar";
console.log("Length:   ", mySparseArray.length);
console.log("0 in it:  ", 0 in mySparseArray);
console.log("arr[0]:   ", mySparseArray[0]);
console.log("10 in it: ", 10 in mySparseArray);
console.log("arr[10]   ", mySparseArray[10]);
console.log("20 in it: ", 20 in mySparseArray);
console.log("arr[20]:  ", mySparseArray[20]);

Alternativ können Sie mit Javascript Ersatz-Arrays einfach initialisieren.

var mySparseArray = ["foo",,,,,,,,,,undefined,{},10,,,,,"bar"];

??????????????????? - ????????????????????

Ein Array-like ist ein Objekt, das mindestens eine length -Eigenschaft hat, jedoch nicht mit new Array Oder [] Initialisiert wurde. Beispielsweise werden die folgenden Objekte als arrayartig klassifiziert.

{0: "foo", 1: "bar", Länge: 2}
document.body.children
neues Uint8Array (3)
  • Dies ähnelt einem Array, da der Konstruktor geändert wird, obwohl es sich um ein a(n) (typisiertes) Array handelt.
(function () {Argumente zurückgeben}) ()

Beobachten Sie, was passiert, wenn Sie eine Methode verwenden, die Array-like in Arrays wie Slice umwandelt.

var slice = Array.prototype.slice;
// For arrays:
console.log(slice.call(["not an array-like, rather a real array"]));
// For array-likes:
console.log(slice.call({0: "foo", 1: "bar", length:2}));
console.log(slice.call(document.body.children));
console.log(slice.call(new Uint8Array(3)));
console.log(slice.call( function(){return arguments}() ));
  • ANMERKUNG: Es ist aus Performancegründen üblich, Slice für Funktionsargumente aufzurufen.

Beobachten Sie, was passiert, wenn Sie eine Methode verwenden, die Array-Likes nicht in Arrays wie concat zwingt .

var empty = [];
// For arrays:
console.log(empty.concat(["not an array-like, rather a real array"]));
// For array-likes:
console.log(empty.concat({0: "foo", 1: "bar", length:2}));
console.log(empty.concat(document.body.children));
console.log(empty.concat(new Uint8Array(3)));
console.log(empty.concat( function(){return arguments}() ));
5
Jack Giffin

Hier ist der Weg der ES6  

var newArray = [];
let dataArray1 = [1,2,3,4]
let dataArray2 = [5,6,7,8]
newArray = [...dataArray1, ...dataArray2]
console.log(newArray)

Die obige Methode ist für die meisten Fälle eine gute Lösung. In den Fällen, in denen dies nicht der Fall ist, sollten Sie concat berücksichtigen, da Sie Hunderttausende von Elementen in Arrays haben.

    let dataArray1 = [1,2,3,4]
    let dataArray2 = [5,6,7,8]
    let newArray = dataArray1.concat(dataArray2);
    console.log(newArray)

3
Black Mamba

Wir haben zwei Felder a und b. Der Code, der hier gemacht wurde, ist Array a value, wird in Array b verschoben.

let a = [2, 4, 6, 8, 9, 15]

function transform(a) {
    let b = ['4', '16', '64']
    a.forEach(function(e) {
        b.Push(e.toString());
    });
    return b;
}

transform(a)

[ '4', '16', '64', '2', '4', '6', '8', '9', '15' ]
0
KARTHIKEYAN.A

Wenn Sie das ursprüngliche Array ändern möchten, können Sie es verteilen und pushen:

var source = [1, 2, 3];
var range = [5, 6, 7];
var length = source.Push(...range);

console.log(source); // [ 1, 2, 3, 5, 6, 7 ]
console.log(length); // 6

Wenn Sie sicherstellen möchten, dass nur Elemente desselben Typs im Array source abgelegt werden (z. B. keine Zahlen und Zeichenfolgen mischen), verwenden Sie TypeScript.

/**
 * Adds the items of the specified range array to the end of the source array.
 * Use this function to make sure only items of the same type go in the source array.
 */
function addRange<T>(source: T[], range: T[]) {
    source.Push(...range);
}
0
orad