Питання Як вставити елемент у масив за певним індексом?


Я шукаю метод вставки масиву Javascript у стилі:

arr.insert(index, item)

Переважно в jQuery, але будь-яка реалізація Javascript буде виконуватись на цьому етапі.


2081
2018-02-25 14:29


походження


Зауважте, що JQuery - це бібліотека маніпулювання DOM та подіями, а не власна мова. Це не має нічого спільного з маніпуляціями масиву. - Jacque Goupil
api.jquery.com/jQuery.inArray не має нічого спільного з DOM чи подіями. jQuery перетворився на змішаний набір інструментів для розробки браузера JS, що призвело до того, що люди сподівалися, що у нього є метод для всього. - Tim
@Tim, Але це ще не є власною мовою (до цих пір є деякі питання, як "як сумувати два числа в jQuery" тут на SO) - Victor
@ Віктор Ні, і ніколи не буде. jQuery було корисним і актуальним, але це був день. - Tim


Відповіді:


Те, що ви хочете, це splice функція на об'єкті native масиву.

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


3447
2018-02-25 14:32



Спасибі, я думав, що я почуваюсь дурним, коли запитую, але тепер, коли я знаю відповідь, я цього не можу! Чому на цьому шляху вони вирішили називати це сплайсинг, коли для однієї і тієї ж функції більш загальнодоступний термін ?! - tags2k
@ tags2k: оскільки функція виконує більше, ніж вставка елементів, і його ім'я вже встановлено в perl? - Christoph
doc: developer.mozilla.org/en/JavaScript/Guide/... - Dingo
Сплісувати може вставити, але так само часто не. Наприклад: arr.splice(2,3) буде видалено 3 елемента, починаючи з індексу 2. Без передачі третього .... N-го параметрів нічого не вставляється. Отже, ім'я insert() не робить цього і справедливості. - EBarr
Я думаю, термін "сплайс" має сенс. Спліс означає приєднуватися або підключатися, також змінюватися. У вас є встановлений масив, який ви зараз "змінюєте", що передбачає додавання або видалення елементів. Ви вказуєте, звідки почати масив, потім скільки старих елементів потрібно видалити (якщо такі є), і, нарешті, необов'язково, список нових елементів для додавання. Звичайно, Splice також є чудовим науково-фантастичним терміном. - Jakub Keller


Ви можете реалізувати 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' ]

208
2017-10-03 14:26



Не змінюйте об'єкти, які ви не володієте - Pavlo
Хто має масив? Ecma script comitee? Я маю на увазі, якщо ви це зробите з Object.defineProperty, можливо, це не так вже й погано, як вважає Павло. - Capaj
Щоб вставити кілька елементів, які можна використовувати Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); } - Ryan Smith
Проблема з додаванням матеріалу до масиву полягає в тому, що функція відображатиметься як елемент, коли ви робите для (i in arr) {...} - rep_movsd
Те, що Павло каже, полягає в тому, що - якщо реалізовано метод native insert, або 2 або більше розробників у вашій компанії вийдуть з тим самим уявленням про створення вставки для об'єкта масиву, але реалізація буде іншою ... Ну, ви отримаєте ідею. - Adam Moszczyński


Користувальницький масив 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/


64
2018-03-25 17:45



Чи існує компактний спосіб для того, щоб ця версія також об'єднувала масив, коли знаходить його в аргументах? - Nolo
@Nolo Так, ви можете знайти його в оновленому відповіді. - VisioN
Я не розумію перший результат ["b", "X", "Y", "Z", "c"]. Чому це не так? "d" включена? Мені здається, що якщо ви поставите 6 як другий параметр slice() і в масиві є 6 елементів починаючи з вказаного індексу, тоді ви повинні отримати всі 6 елементів у поверненому значенні. (Говорить Док howMany за цей параметр.) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Alexis Wilke
Насправді, якщо я використовую індекс з 3 або більше, я нічого не отримую на виході (справа 1., FireFox) ["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3); => [ ] - Alexis Wilke
@AlexisWilke У першому прикладі я використав slice метод, а не splice, про який ви згадуєте в коментарях. Другий параметр slice (названий end) є нульовий індекс, на якому закінчується видобуток. slice витягує до, але не включаючи end. Отже, після insert ти маєш ["a", "b", "X", "Y", "Z", "c", "d"], з якого slice витягує елементи з індексами з 1 аж до 6, тобто від "b" до "d" але не включаючи "d". Це має сенс? - VisioN


За винятком сплайса, ви можете використовувати цей підхід, який не буде змінювати початковий масив, але створить новий масив із доданим елементом. Зазвичай ви повинні уникати мутації, коли це можливо. Я використовую 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]

Це може бути використано для додавання кількох елементів, коригувавши функцію трохи, щоб використовувати оператор відпочинку для нових елементів, і поширювати його в отриманому результаті

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]


54
2017-07-04 09:18



саме відповідь я шукав. Дякую! - Alex Alexeev
Це гарний, безпечний спосіб зробити це? Я питаю, тому що це виглядає настільки елегантно та лаконічно, але ніяких інших відповідей не торкається цього. Більшість з них модифікують об'єкт прототипу! - Harsh Kanchina
@HarshKanchina Це, мабуть, тому, що більшість відповідей є перед ES6, але цей підхід дуже поширений зараз з мого досвіду - Gaafar


Якщо ви хочете вставити декілька елементів в масив одразу перевірте це переповнення Stack: Кращий спосіб об'єднання масиву в масив у 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);

33
2017-08-30 04:37



Чи не буде вставлено (?) Краще, щоб викликати insertArrayAt (), коли він створив елементний елемент arrayToInsert? Це уникає повторення ідентичного коду. - Matt Sach
це чудовий приклад того, коли використовувати "apply" - CRice
Я додав параметр removeCount для цього методу, щоб скористатися перевагами можливості сплайси також видаляти елементи в цьому індексі: Array.prototype.splice.apply (масив, [index, removeCount || 0] .concat (arrayToInsert)); - CRice


Для належного функціонального програмування та ланцюгових цілей винахід 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));


14
2018-05-13 23:22



"абсолютно безглуздий порожній масив" - він повертає тільки порожній масив, коли другий параметр дорівнює 0. Якщо він більше, ніж 0, він повертає елементи, видалені з масиву. Враховуючи, що ви додаєте прототип, і splice мутувати оригінальний масив, я не думаю, що "належне функціональне програмування" належить будь-де в околицях splice. - cdbajorin
Тут мова йде про вставку, а другий параметр Array.prototype.splice () має бути нульовим. І, що він повертає, немає сенсу, крім "я нічого не видалив", і оскільки ми використовуємо його для вставки елемента, у нас вже є ця інформація. Якщо ви не бажаєте змінювати початковий масив, ви можете зробити те ж саме з двома операціями Array.prototype.slice () та одним Array.prototype.concat (). Тобі вирішувати. - Redu
Ваша друга реалізація є найчистішою з цієї всієї сторінки, і у вас є нульові голоси. Будь ласка, візьміть моє і продовжуй хорошу роботу. (ви повинні просто уникнути мутовання прототипу, але ви вже це знаєте) - NiKo
Я вважаю, що варто відзначити, що параметром відпочинку є новий ECMA 6th (developer.mozilla.org/en/docs/Web/JavaScript/Reference/... ) - Geza Turi


Я рекомендую використовувати чистий JavaScript в цьому випадку також немає вставного методу в JavaScript, але у нас є метод, який є a вбудований масив метод, який виконує роботу для вас, це називається сплайсинг...

Давайте подивимося, що є сплайс ()...

Метод splice () змінює вміст масиву, видаливши його   існуючі елементи та / або додавання нових елементів.

Добре, уявіть, що ми маємо цей масив нижче:

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

Ми можемо зняти 3 подобається це:

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

Це поверне 3, але якщо ми перевіримо арр зараз, ми маємо:

[1, 2, 4, 5]

Поки що так добре, але як ми можемо додати новий елемент до масиву, використовуючи сплайсинг? Давайте повернемо 3 в аррі ...

arr.splice(2, 0, 3);

Давайте подивимося, що ми зробили ...

Ми використовуємо сплайсинг знову, але на цей раз для другого аргументу ми проходимо 0означає, що ми хочемо видалити ні один елемент, але в той же час ми додаємо третій аргумент, який буде 3, який буде доданий при другому індексі ...

Ви повинні знати, що ми можемо видалити і додати в той же час, наприклад, тепер ми можемо зробити:

arr.splice(2, 2, 3);

Що буде видалено 2 пункти при індексі 2, потім додати 3 при індексі 2 і результат буде:

[1, 2, 3, 5];

Це показує, як працює кожен елемент у сплайс:

array.splice (початок, deleteCount, item1, item2, item3 ...)


7
2017-12-25 13:04