Jak rozszerzyć istniejącą tablicę JavaScript o inną tablicę, bez tworzenia nowej tablicy?

Uwaga: to jest nie duplikat Jak dodać coś do tablicy? -- celem jest tutaj dodanie całej zawartości jednej tablicy do drugiej i wykonanie tego "na miejscu", tj. bez kopiowania wszystkich elementów rozszerzonej tablicy.

Nie wydaje się, aby można było rozszerzyć istniejącą tablicę JavaScript o inną tablicę, np. aby emulować metodę extend Pythona.

To, co chcę osiągnąć, to:

>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]

Wiem istnieje metoda a.concat(b), ale tworzy nową tablicę zamiast po prostu rozszerzać pierwszą. Chciałbym algorytm, który działa wydajnie, gdy a jest znacznie większy niż b (tzn. taki, który nie kopiuje a).

Author: Community, 2009-09-03

14 answers

The .push metoda może przyjmować wiele argumentów, więc używając .apply aby przekazać wszystkie elementy drugiej tablicy jako argumenty do .push, możesz uzyskać żądany wynik:

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

A może, jeśli uważasz, że jest to jaśniejsze:

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

Jeśli twoja przeglądarka obsługuje ES6, możesz użyć operatora rozprzestrzeniania , który jest bardziej kompaktowy i elegancki:

>>> a.push(...b)

Należy pamiętać, że wszystkie te rozwiązania zawiodą z błędem przepełnienia stosu, jeśli tablica b jest zbyt długi (problem zaczyna się od około 100 000 elementów, w zależności od przeglądarki). Jeśli nie możesz zagwarantować, że b jest wystarczająco krótki, powinieneś użyć standardowej techniki opartej na pętli opisanej w drugiej odpowiedzi.

 1117
Author: DzinX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-21 16:58:21

Aktualizacja 2018: lepsza odpowiedź poniżej: a.push(...b). Nie dyskutuj już o tym, ponieważ nigdy tak naprawdę nie odpowiedział na pytanie, ale był hakerem z 2015 roku wokół pierwszego trafienia w Google:)


Dla tych, którzy po prostu szukali "JavaScript array extend" i dotarli tutaj, możesz bardzo dobrze użyć Array.concat.

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

Concat zwróci kopię nowej tablicy, ponieważ starter wątku nie chciał. Ale może cię to nie obchodzić (na pewno dla większości zastosowań będzie to dobrze).


Jest też do tego jakiś ładny cukier ES6 w postaci operatora spreadu:

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

(także kopie)

 199
Author: odinho - Velmont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-08 11:19:34

Powinieneś użyć techniki opartej na pętli. Inne odpowiedzi na tej stronie, które są oparte na użyciu .apply, mogą nie działać dla dużych tablic.

Dość zwięzła implementacja oparta na pętli to:

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);    
}

Możesz wykonać następujące czynności:

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

Odpowiedź Dzinxa (za pomocą push.Zastosuj) i inne metody oparte na .apply zawodzą, gdy tablica, którą dodajemy jest duża (testy pokazują, że dla mnie duża to > 150000 wpisów w Chrome i > 500000 wpisów w Firefoksie). Zobacz też ten błąd występuje w ten jsperf.

Występuje błąd, ponieważ rozmiar stosu wywołań jest przekroczony, gdy ' funkcja.prototyp.apply ' jest wywoływany z dużą tablicą jako drugim argumentem. (MDN ma notatkę o zagrożeniach związanych z przekroczeniem rozmiaru stosu wywołań przy użyciu funkcji .prototyp.apply - zobacz sekcję "apply i wbudowane funkcje")

Dla porównania prędkości z innymi odpowiedziami na tej stronie sprawdź ten jsperf (Dzięki EaterOfCode). Na implementacja oparta na pętli jest podobna pod względem szybkości do użycia tablicy.przyj.zastosuj, ale wydaje się być trochę wolniejsze niż tablica.plaster.aplikuj.

Co ciekawe, jeśli tablica, którą dodajesz jest rzadka, powyższa metoda oparta na forEach może skorzystać ze sparsity i przewyższyć metody oparte na .apply, Sprawdź ten jsperf jeśli chcesz to przetestować samodzielnie.

Przy okazji, nie daj się skusić (tak jak ja!) w celu dalszego skrócenia realizacji forEach do:

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

Ponieważ daje to wyniki śmieci! Dlaczego? Bo Array.prototyp.forEach dostarcza 3 argumenty wywołanej funkcji - są to: (element_value, element_index, source_array). Wszystkie z nich zostaną wypchnięte na pierwszą tablicę dla każdej iteracji forEach, jeśli użyjesz "forEach (this.push, this)"!

 179
Author: jcdude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:38

Czuję, że najbardziej eleganckie w dzisiejszych czasach jest:

arr1.push(...arr2);

Artykuł MDN o operatorze spreadu wspomina o tym ładnym słodkim sposobie w ES2015 (ES6):

A better push

Przykład: push jest często używany do wypychania tablicy na koniec istniejącego / align = "left" / W ES5 jest to często wykonywane jako:

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

W ES6 z spreadem staje się to:

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

Należy pamiętać, że arr2 nie może być ogromny (trzymać go poniżej około 100 000 pozycji), ponieważ stos połączeń przepełnienia, zgodnie z odpowiedzią jcdude.

 128
Author: odinho - Velmont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 19:51:26

Najpierw kilka słów o apply() w JavaScript, aby pomóc zrozumieć, dlaczego go używamy:

Metoda apply() wywołuje funkcję o podanej wartości this, a argumenty podane jako tablica.

Push oczekuje listy elementów do dodania do tablicy. Metoda apply() pobiera jednak oczekiwane argumenty wywołania funkcji jako tablicę. To pozwala nam łatwo push elementy jednej tablicy do innej tablicy z wbudowanym push() metoda.

Wyobraź sobie, że masz te tablice:

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

I po prostu zrób to:

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

Wynik będzie:

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

To samo można zrobić w ES6 używając operatora spreadu ("...") w następujący sposób:

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

Krótszy i lepszy, ale nie w pełni obsługiwany we wszystkich przeglądarkach w tej chwili.

Również jeśli chcesz przenieść wszystko z tablicy b do a, opróżniając b w procesie, możesz to zrobić:

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

I wynik będzie następujący:

a = [1, 2, 3, 4, 5, 6, 7];
b = [];
 45
Author: Alireza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-28 00:14:02

Jeśli chcesz użyć jQuery, jest $.merge()

Przykład:

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

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

 38
Author: Jules Colle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-24 16:03:32

Podoba mi się opisana powyżej metoda a.push.apply(a, b) i jeśli chcesz, zawsze możesz utworzyć taką funkcję biblioteczną:

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

I użyj go w ten sposób

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

a.append(b)
 18
Author: Pizzaiola Gorgonzola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-11 16:59:13

Można to zrobić używając splice():

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

Ale mimo, że brzydszy nie jest szybszy niż push.apply, przynajmniej Nie w Firefoksie 3.0. Posted for complete sake.

 13
Author: Rafał Dowgird,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-21 08:08:02

Możesz utworzyć polyfill dla extend, jak mam poniżej. Doda się do tablicy; in-place I zwróci się samo, dzięki czemu można łączyć inne metody.

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
Author: Mr. Polywhirl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-17 13:21:34

Widzę bardzo ładne odpowiedzi, a wszystko zależy od rozmiaru tablicy, wymagań i celu. Można to zrobić na różne sposoby.

Sugeruję użycie JavaScript dla pętli:

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

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

console.log(a) wyjście będzie

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

Wtedy możesz utworzyć własną funkcję:

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

console.log(extendArray(a, b)); Wyjście będzie

Array [ 1, 2, 3, 4, 5 ]
 2
Author: maytham-ɯɐɥʇʎɐɯ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-17 14:24:03

Łączenie odpowiedzi...

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]);
        };
    }  
}
 1
Author: zCoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-11 10:10:59

To rozwiązanie działa dla mnie (używając operatora rozproszonego ES6):

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);
 1
Author: Pankaj shrivastava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-05 18:41:41

Inne rozwiązanie scalania więcej niż dwóch tablic

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]);
  }
 }
};

Następnie wywołaj i Drukuj jako:

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

Wyjście będzie: Array [1, 2, 3, 4, 5, 6, 7]

 0
Author: user3126309,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 18:20:36

Odpowiedź jest bardzo prosta.

>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
(the following code will combine the 2 arrays)

a = a.concat(b);

>>> a
[1, 2, 3, 4, 5]

Concat działa bardzo podobnie do JavaScript string concatenation. Zwróci kombinację parametru wprowadzonego do funkcji concat na końcu tablicy, na której wywołujesz funkcję. Najważniejsze jest to, że musisz przypisać zwracaną wartość do zmiennej lub zostanie ona utracona. więc na przykład

a.concat(b);  <---This does absolutely nothing since it is just returning the combined arrays but it doesn't do anything with it
 -2
Author: Timothy Trousdale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 16:27:09