Я шукаю метод вставлення масиву JavaScript у стилі:
arr.insert(index, item)
Переважно в jQuery, але будь-яка реалізація JavaScript буде робити в цей момент.
Я шукаю метод вставлення масиву JavaScript у стилі:
arr.insert(index, item)
Переважно в jQuery, але будь-яка реалізація JavaScript буде робити в цей момент.
Відповіді:
Що ви хочете, це 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());
arr.splice(2,3)
буде видалено 3 елементи, починаючи з індексу 2. Не проходячи 3-го .... Nth параметрів нічого не вставляється. Тож ім'я теж insert()
не справедливо.
Ви можете реалізувати 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' ]
Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }
Крім splice, ви можете використовувати такий підхід, який не буде мутувати вихідний масив, але створить новий масив із доданим елементом. Зазвичай слід уникати мутацій, коли це можливо. Тут я використовую 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]
insert
методи масиву/* 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"]
/* 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"
["b", "X", "Y", "Z", "c"]
. Чому не "d"
включений? Мені здається, що якщо ви поставите 6 як другий параметр, slice()
а в масиві є 6 елементів, починаючи з вказаного індексу, то вам слід отримати всі 6 елементів у зворотному значенні. (Документ говорить howMany
про цей параметр.) Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3);
=>[ ]
slice
метод, а не splice
, про який ви посилаєтесь у коментарі. Другий параметр slice
(названий end
) - нульовий індекс, на якому закінчується видобуток. slice
витяжки до, але не включаючиend
. Тому після того, як у insert
вас є ["a", "b", "X", "Y", "Z", "c", "d"]
, з якого slice
витягує елементи з індексами від 1
до до 6
, тобто від "b"
до , "d"
але не включаючи "d"
. Чи є сенс?
Якщо ви хочете вставити кілька елементів у масив одразу, ознайомтеся з відповіддю на переповнення стека: Кращий спосіб сплавити масив у масив у 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);
Для правильного функціонального цілей програмування та ланцюга важливим є винахід 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));
splice
мутуєте оригінальний масив, я не думаю, що "належне функціональне програмування" належить десь поблизу splice
.
Я рекомендую використовувати чистий JavaScript в цьому випадку, також немає методу вставки в JavaScript, але у нас є метод, який є вбудованим методом масиву, який виконує завдання для вас, він називається сплей ...
Давайте подивимось, що зрощують () ...
Метод splice () змінює вміст масиву, видаляючи існуючі елементи та / або додаючи нові елементи.
Гаразд, уявіть, що ми маємо цей масив нижче:
const arr = [1, 2, 3, 4, 5];
Ми можемо видалити 3
так:
arr.splice(arr.indexOf(3), 1);
Він поверне 3, але якщо ми перевіримо arr зараз, у нас є:
[1, 2, 4, 5]
Поки що так добре, але як ми можемо додати новий елемент до масиву, використовуючи сплайс? Давайте повернемо 3 в arr ...
arr.splice(2, 0, 3);
Подивимося, що ми зробили ...
Ми знову використовуємо сплайс , але цього разу для другого аргументу ми передаємо 0 , це означає, що ми не хочемо видалити жоден елемент, але в той же час ми додаємо третій аргумент, який є 3, який буде доданий у другому індексі ...
Ви повинні знати, що ми можемо одночасно видаляти та додавати , наприклад, зараз:
arr.splice(2, 2, 3);
Що видалить 2 елементи в індексі 2, потім додасть 3 в індексі 2 і результат буде:
[1, 2, 3, 5];
Тут показано, як працює кожен елемент у сплайсі:
array.splice (start, deleteCount, item1, item2, item3 ...)
Додайте окремий елемент у певний індекс
//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
arrName[3] = 'newName1';
, якщо масив містить лише 3 елементи. Якщо в індексі 3 є елемент, його буде замінено. Якщо ви хочете додати в кінці кінців, це краще використовуватиarrName.push('newName1');
Ще одне можливе рішення з використанням 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);
Ось два способи:
const array = [ 'My', 'name', 'Hamza' ];
array.splice(2, 0, 'is');
console.log("Method 1 : ", array.join(" "));
АБО
Array.prototype.insert = function ( index, item ) {
this.splice( index, 0, item );
};
const array = [ 'My', 'name', 'Hamza' ];
array.insert(2, 'is');
console.log("Method 2 : ", array.join(" "));
Хоча на це вже відповіли, я додаю цю замітку для альтернативного підходу.
Я хотів розмістити відому кількість елементів у масиві, в конкретні позиції, оскільки вони виходять з "асоціативного масиву" (тобто об'єкта), який за визначенням не гарантується в упорядкованому порядку. Я хотів, щоб отриманий масив був масивом об'єктів, але об'єкти мають бути в певному порядку в масиві, оскільки масив гарантує їх порядок. Тому я це зробив.
Спочатку об'єкт-джерело - рядок JSONB, отриманий з PostgreSQL. Я хотів, щоб це було відсортовано за властивістю "порядку" у кожному дочірньому об'єкті.
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);
Той, хто все ще має проблеми з цим, і спробував усі варіанти, описані вище, і ніколи його не отримав. Я ділюсь своїм рішенням, щоб врахувати, що ви не хочете явно вказати властивості вашого об'єкта проти масиву.
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;
}
Це комбінація ітерації опорного масиву та порівняння його з об'єктом, який ви хотіли перевірити, перетворити їх обидва в рядок, а потім ітераціювати, якщо він збігався. Тоді можна просто порахувати. Це можна покращити, але саме тут я оселився. Сподіваюсь, це допомагає.
Отримання прибутку методу зменшення таким чином:
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 або зрощення) з елементом, вставленим в індексі, і якщо індекс більший за довжину масиву, він буде вставлений в кінці.
Array#splice()
це шлях, якщо ви дійсно не хочете уникати мутування масиву. З огляду на 2 масивів arr1
і arr2
, ось як ви б вставити вміст arr2
в arr1
після першого елемента:
const arr1 = ['a', 'd', 'e'];
const arr2 = ['b', 'c'];
arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']
console.log(arr1)
Якщо вас турбує мутація масиву (наприклад, якщо ви використовуєте Immutable.js), ви можете замість цього використовувати slice()
, не плутати splice()
з a 'p'
.
const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];
Я спробував це, і це працює чудово!
var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);
Індекс - це місце, куди потрібно вставити або видалити елемент. 0, тобто другий параметр визначає кількість елемента з індексу, що підлягає вилученню, це нові записи, які ви хочете зробити в масиві. Це може бути один або декілька.
initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");
Ось робоча функція, яку я використовую в одному зі своїх додатків.
Це перевіряє, чи є вихід
let ifExist = (item, strings = [ '' ], position = 0) => {
// output into an array with empty string. Important just in case their is no item.
let output = [ '' ];
// check to see if the item that will be positioned exist.
if (item) {
// output should equal to array of strings.
output = strings;
// use splice in order to break the array.
// use positition param to state where to put the item
// and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position.
output.splice(position, 0, item);
}
//empty string is so we do not concatenate with comma or anything else.
return output.join("");
};
А потім я називаю це нижче.
ifExist("friends", [ ' ( ', ' )' ], 1)} // output: ( friends )
ifExist("friends", [ ' - '], 1)} // output: - friends
ifExist("friends", [ ':'], 0)} // output: friends:
Трохи старіший потік, але я маю згоду зі зменшеним вище, тому що у сплеску напевно є трохи заплутаний інтерфейс. І відповідь, надана cdbajorin, що "він повертає порожній масив лише тоді, коли другий параметр дорівнює 0. Якщо він більший за 0, він повертає елементи, вилучені з масиву", є, хоча й точним, доводить суть. Метою функції є з'єднання або, як раніше говорив Якоб Келлер, "приєднатись або підключитися, також змінити. У вас є встановлений масив, який ви зараз змінюєте, який би передбачав додавання або видалення елементів ...." Враховуючи це, повернути значення повернених елементів, якщо такі є, в кращому випадку незручно. І я на 100% погоджуюся, що цей метод міг би бути більш підходящим для прив'язування ланцюгів, якби він повернув те, що здається природним, додав новий масив із доданими елементами. Тоді ви можете робити такі речі, як ["19", "17"]. Splice (1,0, "18"). Join ("...") або все, що завгодно, з поверненим масивом. Той факт, що він повертає те, що було видалено, - це просто своєрідна дурниця IMHO. Якщо мета методу полягала в тому, щоб "вирізати набір елементів", і це був лише намір, можливо. Схоже, якщо я вже не знаю, що я вирізаю, хоча, мабуть, у мене мало підстав вирізати ці елементи, чи не так? Було б краще, якби він поводився як concat, map, зменшення, зріз тощо, де новий масив створений з існуючого масиву, а не мутування існуючого масиву. Це все можливо, і це важливе питання. Це досить поширене для маніпулювання ланцюговим масивом. Здається, що мова повинна йти в той чи інший бік і намагатися дотримуватися її якомога більше. Javascript є функціональним і менш декларативним, це просто здається дивним відхиленням від норми.
Сьогодні (2020.04.24) я виконую тести для обраних рішень для великих та малих масивів. Я тестував їх на MacOs High Sierra 10.13.6 на Chrome 81.0, Safari 13.1, Firefox 75.0.
Для всіх браузерів
slice
і reduce
(D, E, F) зазвичай на 10x-100x швидше, ніж на місціsplice
(AI, BI, CI), були найшвидшими (іноді ~ 100x - але це залежить від розміру масиву)Тести були поділені на дві групи: розчини на місці (AI, BI, CI) та не на місці рішення (D, E, F) та виконувались у двох випадках
Тестований код представлений в нижній частині фрагмента
Нижче наведено приклади результатів для малого масиву на хромі