Как расширить существующий массив JavaScript другим массивом, не создавая новый массив?

Примечание: это не дубликат как добавить что-то в массив? -- цель здесь состоит, чтобы добавить содержимое одного массива в другой, и делать это "на месте", т. е. без копирования всех элементов расширенного массива.

кажется, что нет способа расширить существующий массив JavaScript другим массивом, т. е. эмулироватьextend метод.

чего я хочу добиться-это следующее:

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

Я знаю, что есть a.concat(b) способ, но он создает новый массив, вместо того, чтобы просто продлить первый. Я хотел бы алгоритм, который работает эффективно, когда a - это значительно больше, чем b (т. е. не копирует a).

14 ответов


The .push метод может принимать несколько аргументов, с помощью .apply пройти все элементы второго массива в качестве аргументов .push, вы можете получить результат вы хотите:

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

или, возможно, если вы думаете, что это яснее:

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

если Ваш браузер поддерживает ES6, вы можете использовать распространение оператор, который более компактен и элегантен:

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

обратите внимание, что все эти решения произойдет сбой с ошибкой переполнения стека, если array b слишком длинный (проблема начинается примерно с 100 000 элементов, в зависимости от браузера). Если вы не можете гарантировать это b достаточно короткий, вы должны использовать стандартный метод на основе цикла, описанный в другом ответе.


обновить 2018: лучше ответить ниже: a.push(...b). Не поднимайте этот вопрос больше, так как он никогда не отвечал на вопрос, но был взломом 2015 года вокруг первого хита-на-Google :)


для тех, кто просто искал "JavaScript array extend" и попал сюда, вы можете очень хорошо использовать Array.concat.

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

Concat вернет копию нового массива, так как стартер потока не хотел. Но вам может быть все равно (конечно, для большинства видов использует это будет хорошо).


для этого есть также хороший сахар ES6 в виде оператора распространения:

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

(тоже копии)


вы должны использовать метод на основе цикла. Другие ответы на этой странице, основанные на использовании .apply может не для больших массивов.

довольно лаконичная реализация на основе цикла:

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

затем вы можете сделать следующее:

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

DzinX это!--15--> (используя push.применить) и другие .apply основанные методы терпят неудачу, когда массив, который мы добавляем, большой (тесты показывают, что для меня большой - > 150000 записей приблизительно в Chrome и > 500000 записей в Firefox). Вы можете увидеть эту ошибку, возникающую в см. Этот тест jsperf.

ошибка возникает из-за превышения размера стека вызовов, когда функция.прототип.apply ' вызывается с большим массивом в качестве второго аргумента. (MDN имеет примечание об опасностях превышения размера стека вызовов с помощью


Я чувствую себя самым элегантным в эти дни:

arr1.push(...arr2);

на статья MDN об операторе распространения упоминает этот приятный сладкий способ в ES2015 (ES6):

лучший толчок

пример: push часто используется для перемещения массива в конец существующего матрица. В ES5 это часто делается как:

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

в ES6 с распространением это становится:

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

отметим, что arr2 не может быть огромным (keep это около 100 000 элементов), потому что стек вызовов переполняется, согласно ответу jcdude.


сначала несколько слов о apply() в JavaScript, чтобы помочь понять, почему мы используем это:

на apply() метод вызывает функцию с заданным this значением, и аргументы в виде массива.

нажимаем ожидает список товары для добавления в массив. The apply() метод, однако, принимает ожидаемые аргументы для вызова функции в виде массива. Это позволяет нам легко push элементы одного массива в другой массив со встроенным push() метод.

представьте, что у вас есть эти массивы:

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

и просто сделать это:

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

результат будет такой:

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

то же самое можно сделать в ES6 с помощью оператора spread ("...") такой:

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

короче и лучше, но не полностью поддерживается всеми браузерами на данный момент.

если вы хотите движение все из массива b to a очистка b в процессе, вы можете сделать это:

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

и результат будет следующим:

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

Если вы хотите использовать jQuery, то есть $.merge ()

пример:

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

результат: a = [1, 2, 3, 4, 5]


мне нравится a.push.apply(a, b) метод, описанный выше, и если вы хотите, вы всегда можете создать библиотечную функцию, как это:

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

и использовать его в таком виде

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

a.append(b)

Это можно сделать с помощью splice():

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

но несмотря на то, что уродливее не быстрее, чем push.apply, по крайней мере, не в Firefox 3.0. Выложил для полноты картины.


вы можете создать polyfill для extend, как показано ниже. Он будет добавлять в массив; на месте и возвращать себя, так что вы можете связать другие методы.

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

Я вижу очень хорошие ответы, и все зависит от вашего размера массива, вашего требования и цели. Это можно сделать по-разному.

Я предлагаю использовать JavaScript для петли:

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

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

console.log(a) выход будет

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

затем вы можете сделать свою собственную функцию:

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

console.log(extendArray(a, b)); выход будет

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

объединение ответов...

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

Это решение работает для меня(используя оператор распространения 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);

другое решение для объединения более чем двух массивов

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

затем вызовите и распечатайте как:

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

результат должен выглядеть так: Array [1, 2, 3, 4, 5, 6, 7]


ответ очень прост.

>>> 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 действует очень похоже на конкатенацию строк javascript. Он вернет комбинацию параметра, который вы помещаете в функцию concat в конце массива, на котором вы вызываете функцию. Суть в том, что вы должны присвоить возвращаемое значение переменной, или оно потеряется. так, например,

a.concat(b);  <---This does absolutely nothing since it is just returning the combined arrays but it doesn't do anything with it