Как вставить элемент в массив по определенному индексу (JavaScript)?

2294

Я ищу метод вставки массива JavaScript в стиле:

arr.insert(index, item)

Предпочтительно в jQuery, но любая реализация JavaScript будет делать в этот момент.

  • 70
    Обратите внимание, что JQuery - это библиотека DOM и управления событиями, а не собственный язык. Это не имеет ничего общего с манипулированием массивами.
  • 19
    api.jquery.com/jQuery.inArray не имеет ничего общего с DOM или событиями. jQuery превратился в смешанный инструментарий для разработки JS-браузеров, в результате чего люди ожидают, что у него будет метод для всего.
Показать ещё 3 комментария
Теги:
arrays
insert

14 ответов

3766
Лучший ответ

То, что вы хотите, - это функция splice на собственном массиве.

arr.splice(index, 0, item); будет вставлять item в arr по указанному индексу (сначала удаляя 0 элементов, то есть просто вставку).

В этом примере мы создадим массив и добавим в него элемент в индекс 2:

var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";

console.log(arr.join());
arr.splice(2, 0, "Lene");
console.log(arr.join());
  • 140
    Спасибо, я думал, что буду глупо спрашивать, но теперь, когда я знаю ответ, я не знаю! С какой стати они решили называть это сплайсингом, когда для той же функции обычно используется более удобный для поиска термин ?!
  • 72
    @ tags2k: потому что функция делает больше, чем просто вставляет элементы, и ее имя уже установлено в perl?
Показать ещё 16 комментариев
227

Вы можете реализовать метод Array.insert, выполнив следующие действия:

Array.prototype.insert = function ( index, item ) {
    this.splice( index, 0, item );
};

Затем вы можете использовать его так:

var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');

// => arr == [ 'A', 'B', 'C', 'D', 'E' ]
  • 7
    Чтобы вставить несколько элементов, вы можете использовать Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }
  • 6
    Проблема с добавлением материала в массив состоит в том, что функция будет отображаться как элемент, когда вы делаете для (я в arr) {...}
Показать ещё 2 комментария
66

Кроме сращивания, вы можете использовать этот подход, который не будет мутировать исходный массив, но создаст новый массив с добавленным элементом. Обычно вам следует избегать мутации. Я использую оператор распространения ES6 здесь.

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, newItem) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted item
  newItem,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10)

console.log(result)
// [1, 10, 2, 3, 4, 5]

Это может быть использовано для добавления нескольких элементов путем настройки функции бит для использования оператора rest для новых элементов и распространения этого результата в возвращенном виде.

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, ...newItems) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted items
  ...newItems,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10, 20)

console.log(result)
// [1, 10, 20, 2, 3, 4, 5]
  • 0
    Это хороший, безопасный способ сделать это? Я спрашиваю, потому что это кажется таким элегантным и кратким, но никакие другие ответы не касаются этого. Большинство из них модифицируют прототип объекта!
  • 1
    @HarshKanchina Это, вероятно, потому что большинство ответов до ES6, но этот подход очень распространен сейчас из моего опыта
63

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

1. С несколькими аргументами и поддержкой цепочки

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    this.splice.apply(this, [index, 0].concat(
        Array.prototype.slice.call(arguments, 1)));
    return this;
};

Он может вставлять несколько элементов (как родной splice) и поддерживает цепочку:

["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]

2. С поддержкой массива слияния и привязки аргументов

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    index = Math.min(index, this.length);
    arguments.length > 1
        && this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
        && this.insert.apply(this, arguments);
    return this;
};

Он может объединять массивы из аргументов с данным массивом, а также поддерживает цепочку:

["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"

DEMO: http://jsfiddle.net/UPphH/

  • 0
    Есть ли компактный способ слияния этой версии с массивом, когда он находит его в аргументах?
  • 0
    @Nolo Да, вы можете найти его в обновленном ответе.
Показать ещё 3 комментария
33

Если вы хотите вставить несколько элементов в массив сразу, проверьте этот ответ: лучший способ сращить массив в массив в javascript

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

function insertAt(array, index) {
    var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
    return insertArrayAt(array, index, arrayToInsert);
}

function insertArrayAt(array, index, arrayToInsert) {
    Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
    return array;
}

Наконец, вот jsFiddle, чтобы вы могли увидеть это для себя: http://jsfiddle.net/luisperezphd/Wc8aS/

Вот как вы используете функции:

// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");

// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);
  • 1
    Разве не будет insertAt () лучше вызывать insertArrayAt () после создания одноэлементного arrayToInsert? Это позволяет избежать повторения идентичного кода.
  • 1
    это отличный пример того, когда использовать «применить»
Показать ещё 1 комментарий
15

Для правильного функционального программирования и целенаправленности важно изобретение Array.prototype.insert(). На самом деле сплайсинг мог бы быть идеальным, если бы он вернул мутированный массив вместо абсолютно бессмысленного пустого массива. Итак, вот оно

Array.prototype.insert = function(i,...rest){
  this.splice(i,0,...rest)
  return this
}

var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");

Хорошо, что выше с помощью Array.prototype.splice() один мутирует исходный массив, а некоторые могут жаловаться, как "вы не должны изменять то, что не принадлежит вам", и это может оказаться правильным. Поэтому для общественного благосостояния я хотел бы дать еще один Array.prototype.insert(), который не будет мутировать исходный массив. Вот оно:

Array.prototype.insert = function(i,...rest){
  return this.slice(0,i).concat(rest,this.slice(i));
}

var a = [3,4,8,9],
    b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));
  • 2
    «абсолютно бессмысленный пустой массив» - он возвращает пустой массив только тогда, когда второй параметр равен 0. Если он больше 0, он возвращает элементы, удаленные из массива. Учитывая, что вы добавляете в прототип, а splice изменяет исходный массив, я не думаю, что «правильное функциональное программирование» относится к области splice .
  • 0
    Здесь речь идет о вставке, и второй параметр Array.prototype.splice () должен быть нулевым. И то, что он возвращает, не имеет никакого значения, кроме «я ничего не удалил», и поскольку мы используем его для вставки элемента, у нас уже есть эта информация. Если вы не хотите изменять исходный массив, вы можете сделать то же самое с двумя операциями Array.prototype.slice () и одной операцией Array.prototype.concat (). Тебе решать.
Показать ещё 2 комментария
9

В этом случае я рекомендую использовать чистый JavaScript, также нет метода вставки в JavaScript, но у нас есть метод, который является встроенным методом Array, который выполняет задание для вас, он называется splice...

Посмотрим, что splice()...

Метод splice() изменяет содержимое массива путем удаления существующих элементов и/или добавления новых элементов.

ОК, представьте, что у нас есть этот массив ниже:

const arr = [1, 2, 3, 4, 5];

Мы можем удалить 3 следующим образом:

arr.splice(arr.indexOf(3), 1);

Он вернет 3, но если мы проверим arr сейчас, у нас есть:

[1, 2, 4, 5]

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

arr.splice(2, 0, 3);

Посмотрим, что мы сделали...

Мы снова используем сплайсинг, но на этот раз для второго аргумента мы передаем 0, значит, мы хотим удалить элемент, но в то же время добавим третий аргумент, который будет добавлен во втором индексе...

Вы должны знать, что мы можем удалить и добавить одновременно, например, теперь мы можем сделать:

arr.splice(2, 2, 3);

Который удалит 2 элемента в индексе 2, затем добавит 3 по индексу 2, и результат будет:

[1, 2, 3, 5];

Это показывает, как работают каждый элемент в сращивании:

array.splice(start, deleteCount, item1, item2, item3...)

8

Это:

var arr= ["India","China","Japan","USA"];

arr.splice(index, 0, item);

Введет элемент в arr с указанным index (сначала удалив 0 элементов, то есть просто вставку).

5

Другое возможное решение с использованием Array#reduce.

var arr = ["apple", "orange", "raspberry"],
    arr2 = [1, 2, 4];

function insert(arr, item, index) {
    arr = arr.reduce(function(s, a, i) {
      i == index ? s.push(item, a) : s.push(a);
      return s;
    }, []);   
    console.log(arr);
}

insert(arr, "banana", 1);
insert(arr2, 3, 2);
5

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

Я хотел помещать известное количество элементов в массив в определенные позиции, поскольку они отрываются от "ассоциативного массива" (т.е. объекта), который по определению не гарантированно находится в отсортированном порядке. Я хотел, чтобы результирующий массив был массивом объектов, но объекты были в определенном порядке в массиве, так как массив гарантирует их порядок. Поэтому я сделал это.

Сначала исходный объект, строка JSONB, полученная из PostgreSQL. Я хотел, чтобы он отсортировался по свойству "order" в каждом дочернем объекте.

var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';

var jsonb_obj = JSON.parse(jsonb_str);

Поскольку число узлов в объекте известно, я сначала создаю массив с указанной длиной:

var obj_length = Object.keys(jsonb_obj).length;
var sorted_array = new Array(obj_length);

И затем повторите попытку объекта, помещая вновь созданные временные объекты в нужные места в массиве без какой-либо "сортировки".

for (var key of Object.keys(jsonb_obj)) {
  var tobj = {};
  tobj[key] = jsonb_obj[key].abbr;

  var position = jsonb_obj[key].order - 1;
  sorted_array[position] = tobj;
}

console.dir(sorted_array);
4

Добавить единый элемент по определенному индексу

//Append at specific position(here at index 1)
arrName.splice(1, 0,'newName1');
//1: index number, 0: number of element to remove, newName1: new element


//Append at specific position (here at index 3)
arrName[3] = 'newName1';

Добавить несколько элементов по определенному индексу

//Append from index number 1
arrName.splice(1, 0,'newElemenet1', 'newElemenet2', 'newElemenet3');
//1: index number from where append start, 
//0: number of element to remove, 
//newElemenet1,2,3: new elements
  • 4
    Стоит отметить, что arrName [3] не добавляется, оно переопределяет.
  • 0
    Он добавляет элемент в существующий массив без перегрузки, например: let arrName = ['xxx', 'yyy', 'zzz']; arrName.splice (1, 0, «aaa», «bbb», «ccc»); после печати arrName
Показать ещё 3 комментария
2

Я пробовал это, и он работает нормально!

var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);

Индекс - это позиция, в которую вы хотите вставить или удалить элемент. 0, т.е. Второй параметр определяет количество элементов из объекта, подлежащего удалению, - это новые записи, которые вы хотите создать в массиве. Это может быть один или несколько.

initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");
  • 2
    просто скопируйте и вставьте ответ выше. это не добавляет никакой ценности к вопросу. либо вы добавляете новый ответ, либо комментируете существующий. пожалуйста, попробуйте внести что-то новое. мы не хотим портить это сообщество
1

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

function isIdentical(left, right){
    return JSON.stringify(left) === JSON.stringify(right);
}

function contains(array, obj){
    let count = 0;
    array.map((cur) => {
          if(this.isIdentical(cur, obj)) count++;
    });
    return count > 0;
}

Это комбинация итерации массива ссылок и сравнение его с объектом, который вы хотите проверить, преобразовать оба из них в строку, а затем повторить, если она соответствует. Тогда вы можете просто посчитать. Это можно улучшить, но это то, где я поселился. Надеюсь это поможет.

0

Взятие прибыли по методу снижения следующим образом:

function insert(arr, val, index) {
    return index >= arr.length 
        ? arr.concat(val)
        : arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);
}

Таким образом, таким способом мы можем вернуть новый массив (это будет классный функциональный способ - гораздо лучше, чем использовать push или splice) с элементом, вставленным в index, и если индекс больше длины массива, он будет вставлен в конце.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню