Подтвердить что ты не робот

Javascript - вставить массив внутри другого массива

Каков более эффективный способ вставки массива внутри другого массива.

a1 = [1,2,3,4,5];
a2 = [21,22];

newArray - a1.insertAt(2,a2) -> [1,2, 21,22, 3,4,5];

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

Спасибо.

4b9b3361

Ответ 1

Вы можете использовать splice в сочетании с некоторыми трюками apply:

a1 = [1,2,3,4,5];
a2 = [21,22];

a1.splice.apply(a1, [2, 0].concat(a2));

console.log(a1); // [1, 2, 21, 22, 3, 4, 5];

В ES2015 + вы можете использовать оператор с расширением, чтобы сделать это немного приятнее

a1.splice(2, 0, ...a2);

Ответ 2

Сначала это было неправильно. Должен был использовать concat() вместо этого.

var a1 = [1,2,3,4,5],
    a2 = [21,22],
    startIndex = 0,
    insertionIndex = 2,
    result;    

result = a1.slice(startIndex, insertionIndex).concat(a2).concat(a1.slice(insertionIndex));

Пример: http://jsfiddle.net/f3cae/1/

Это выражение использует slice(0, 2) [docs] для возврата первых двух элементов a1 (где 0 - начальный индекс, а 2 - элемент deleteCount, хотя a1 не изменяется).

Промежуточный результат: [1,2]

Затем он использует concat(a2) [docs] для добавления a2 в конец [1,2].

Промежуточный результат: [1,2,21,22].

Затем a1.slice(2) вызывается в конце .concat() в конце этого выражения, что составляет [1,2,21,22].concat(a1.slice(2)).

Вызов slice(2) с положительным целочисленным аргументом вернет все элементы после 2-го элемента, считая на натуральные числа (как, например, есть пять элементов, поэтому [3,4,5] будет возвращено из a1), Другой способ сказать, что аргумент единственного целочисленного индекса сообщает a1.slice() с какой позиции массива начинать возвращать элементы (индекс 2 является третьим элементом).

Промежуточный результат: [1,2,21,22].concat([3,4,5])

Наконец, второй .concat() добавляет [3,4,5] в конец [1,2,21,22].

Результат: [1,2,21,22,3,4,5]

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

Тем не менее, для тех, кто живет на краю...

Пример: http://jsfiddle.net/f3cae/2/

Array.prototype.injectArray = function( idx, arr ) {
    return this.slice( 0, idx ).concat( arr ).concat( this.slice( idx ) );
};

var a1 = [1,2,3,4,5];
var a2 = [21,22];

var result = a1.injectArray( 2, a2 );

Ответ 3

Теперь вы можете сделать это, если используете ES2015 или новее:

var a1 = [1,2,3,4,5];
var a2 = [21,22];
a1.splice(2, 0, ...a2);
console.log(a1) // => [1,2,21,22,3,4,5]

Обратитесь к этому вопросу для документации по оператору распространения (...) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

Ответ 4

Я хотел найти способ сделать это с помощью splice() и не выполнять итерации: http://jsfiddle.net/jfriend00/W9n27/.

a1 = [1,2,3,4,5];
a2 = [21,22];

a2.unshift(2, 0);          // put first two params to splice onto front of array
a1.splice.apply(a1, a2);   // pass array as arguments parameter to splice
console.log(a1);           // [1, 2, 21, 22, 3, 4, 5];

В форме общего назначения:

function arrayInsertAt(destArray, pos, arrayToInsert) {
    var args = [];
    args.push(pos);                           // where to insert
    args.push(0);                             // nothing to remove
    args = args.concat(arrayToInsert);        // add on array to insert
    destArray.splice.apply(destArray, args);  // splice it in
}

Ответ 5

Оператор spread позволяет расширять выражение в местах, где несколько аргументов (для вызовов функций) или нескольких элементов (для массива литералы).

a2 = [21,22];
a1 = [1,2,...a2,3,4,5];//...a2 is use of spread operator
console.log(a1);

Ответ 6

var a1 = [1,2,3,4,5];
var a2 = [21,22];

function injectAt(d, a1, a2) {
    for(var i=a1.length-1; i>=d; i--) {
        a1[i + a2.length] = a1[i];
    }
    for(var i=0; i<a2.length; i++) {
        a1[i+d] = a2[i];
    }
}

injectAt(2, a1, a2);

alert(a1);

Ответ 7

Здесь моя версия без особых трюков:

function insert_array(original_array, new_values, insert_index) {
    for (var i=0; i<new_values.length; i++) {
        original_array.splice((insert_index + i), 0, new_values[i]);
    }
    return original_array;
}

Ответ 8

Если вы хотите вставить другой массив в массив без создания нового, проще всего использовать либо push, либо unshift с apply

Например:

a1 = [1,2,3,4,5];
a2 = [21,22];

// Insert a1 at beginning of a2
a2.unshift.apply(a2,a1);
// Insert a1 at end of a2
a2.push.apply(a2,a1);

Это работает, потому что и push, и unshift принимают переменное количество аргументов. Бонус, вы можете легко выбрать, к какому концу присоединить массив!

Ответ 9

Как упоминалось в другом потоке, ответы выше не будут работать в очень больших массивах (элементы 200K). См. Альтернативный ответ здесь, в том числе с использованием сплайсинга и ручного нажатия: fooobar.com/questions/2408/...

Array.prototype.spliceArray = function(index, insertedArray) {
    var postArray = this.splice(index);
    inPlacePush(this, insertedArray);
    inPlacePush(this, postArray);

    function inPlacePush(targetArray, pushedArray) {
  // Not using forEach for browser compatability
        var pushedArrayLength = pushedArray.length;
        for (var index = 0; index < pushedArrayLength; index++) {
           targetArray.push(pushedArray[index]);
       }
    }
}

Ответ 10

Здесь есть действительно креативные ответы на этот вопрос. Вот простое решение для тех, кто только начинает с массивов. При желании его можно заставить работать до браузеров, совместимых с ECMAScript 3.

Знать кое-что о сращивании, прежде чем начать.

Сеть разработчиков Mozilla: Array.prototype.splice()

Во-первых, поймите две важные формы .splice().

let a1 = [1,2,3,4],
    a2 = [1,2];

Способ 1) Удалить элементы x (deleteCount), начиная с нужного индекса.

let startIndex = 0, 
    deleteCount = 2;

a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]

Способ 2) Удалите элементы после нужного начального индекса до конца массива.

a1.splice(2); // returns [3,4], a1 would be [1,2]

Используя .splice(), цель может состоять в том, чтобы разделить a1 на головной и хвостовой массивы, используя одну из двух форм выше.

Используя метод # 1, возвращаемое значение станет головой, а a1 хвостом.

let head = a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]

Теперь одним махом соедините голову, тело (a2) и хвост

[].concat(head, a2, a1);

Таким образом, это решение больше похоже на реальный мир, чем любое другое представленное до сих пор. Разве это не то, что вы бы сделали с Legos? ;-) Вот функция, выполненная с использованием метода # 2.

/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*/
function insertArray(target, body, startIndex)
{
    let tail = target.splice(startIndex); // target is now [1,2] and the head
    return [].concat(target, body, tail);
}

let newArray = insertArray([1, 2, 3, 4], ["a", "b"], 2); // [1, 2, "a", "b", 3, 4]

Короче:

/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*/
function insertArray(target, body, startIndex)
{
    return [].concat(target, body, target.splice(startIndex));
}

безопаснее:

/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*@throws Error The value for startIndex must fall between the first and last index, exclusive.
*/
function insertArray(target, body, startIndex)
{
    const ARRAY_START = 0,
          ARRAY_END = target.length - 1,
          ARRAY_NEG_END = -1,
          START_INDEX_MAGNITUDE = Math.abs(startIndex);

    if (startIndex === ARRAY_START) {
        throw new Error("The value for startIndex cannot be zero (0).");
    }

    if (startIndex === ARRAY_END || startIndex === ARRAY_NEG_END) {
        throw new Error("The startIndex cannot be equal to the last index in target, or -1.");
    }

    if (START_INDEX_MAGNITUDE >= ARRAY_END) {
        throw new Error("The absolute value of startIndex must be less than the last index.");
    }

    return [].concat(target, body, target.splice(startIndex));
}

Преимущества этого решения включают в себя:

1) Простая предпосылка доминирует над решением - заполните пустой массив.

2) Голова, тело и хвост номенклатура чувствует себя естественно.

3) Нет двойного вызова .slice(). Нет нарезки на всех.

4) Нет .apply(). Весьма ненужно.

5) Метод цепочки избегается.

6) Работает в ECMAScript 3 и 5 просто используя var вместо let или const.

** 7) Гарантирует, что голова и хвост будут шлепать по телу, в отличие от многих других представленных решений. Если вы добавляете массив до или после границ, вы должны по крайней мере использовать .concat() !!!!

Примечание. Использование распределительного оператора ... делает все это намного проще.