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


У мене є масив цілих чисел, і я використовую .push() метод додати до нього елементи.

Чи є простий спосіб видалення певного елемента з масиву? Еквівалент щось на кшталт array.remove(int);.

Я повинен використовувати ядро JavaScript - немає рамки дозволяються.


6131
2018-04-23 22:17


походження


Якщо вам потрібно підтримати <IE9 (зітхає), потім перевірте це СО питання відносно indexOf в IE. - Scotty.NET
(lodash) array = ['a', 'b', 'c']; _.pull (масив, 'a') // array => ['b', 'c']; Дивись також stackoverflow.com/questions/5767325/... - Chun Yang
метод фільтрації може робити те, що хочеш. - Salvador Dali
Ви можете скористатись видаленням, але він не змінить індекс замість цього, він встановить цей слот на "undefined × 1". Наприклад: var list = [1,2,3,4,5,6] -> видалити список [1] ​​-> [1, undefined × 1, 3, 4, 5, 6]. - DevWL
Ось тестовий показник двох основних можливостей: jsben.ch/#/b4Ume - EscapeNetscape


Відповіді:


Знайди index елемента масиву, який ви хочете видалити, а потім видаліть цей індекс за допомогою splice.

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

var array = [2, 5, 9];
var index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}
// array = [2, 9]

Другий параметр splice це кількість елементів для видалення. Зауважте, що splice змінює масив на місці і повертає новий масив, що містить елементи, які були вилучені.


Примітка: підтримка браузера для indexOf обмежений


8923
2018-04-23 22:23



@ Петр, так, ви, можливо, маєте рацію. У цій статті пояснюється більше, і є шляхи вирішення проблеми несумісних браузерів: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/... - Tom Wadley
Небезпечний! Якщо ви працюєте з динамічними значеннями (додавайте та видаляйте динамічні значення з масиву), а значення в масиві не існує (індекс стає -1), то код вище буде видаляти останній елемент масиву. - Adrian P.
@AlexandreWiechersVaz Звичайно, це зберігає порядок, якщо це не було, то це було б абсолютно нікчемно - TheZ
Ви можете подолати проблему підтримки браузера IE, включивши код дано тут
@AdrianP array.indexOf(testValue) на порожньому масиві буде -1, і якщо ви пробуватимете для цього, то не сплайси. Може, відповідь змінився з того часу. - UpTheCreek


Я не знаю, як ви очікуєте array.remove(int) для себе. Є три можливості, я можу думати про те, що ви, можливо, бажаєте.

Видалити елемент масиву за індексом i:

array.splice(i, 1);

Якщо ви хочете видалити кожен елемент зі значенням number з масиву:

for(var i = array.length - 1; i >= 0; i--) {
    if(array[i] === number) {
       array.splice(i, 1);
    }
}

Якщо ви просто хочете зробити елемент у індексі i більше не існує, але ви не хочете змінювати індекси інших елементів:

delete array[i];

896
2018-04-23 22:20



delete це не правильний спосіб видалення елемента з масиву! - Felix Kling
@FelixKling Це залежить, він працює, якщо ви хочете зробити це так array.hasOwnProperty(i) повертає false і мати елемент у цій позиції повернення undefined. Але я визнаю, що це не дуже поширена річ, яку потрібно зробити. - Peter Olson
delete не буде оновлювати довжину масиву або дійсно стирає елемент, лише замінює його спеціальним значенням undefined. - diosney
@diosney Я не знаю, що ви маєте на увазі, коли ви говорите, що це дійсно не стирає елемент. Крім того, це більше, ніж просто заміна значення в цьому індексі за допомогою undefined: він видаляє як індекс, так і значення з масиву, тобто після delete array[0], "0" in array повернемо помилково. - Peter Olson
Видалення - це хороший механізм, якщо ви маєте справу з названими властивостями var array=[];array['red']=1;array['green']=2;array['blue']=3;delete array['green']; - Jefferey Cave


Відредаговано на жовтень 2016 року

  • Зробіть це простим, інтуїтивно зрозумілим і явним (https://en.wikipedia.org/wiki/Occam%27s_razor)
  • Зробіть це незмінним (первинний масив залишається незмінним)
  • Зробіть це за допомогою стандартних функцій JS, якщо ваш браузер не підтримує їх - використовувати поліфіль

У цьому прикладі коду я використовую "масив.фільтр (...)" функція для видалення небажаних елементів з масиву, ця функція не змінює оригінальний масив і створює новий. Якщо ваш браузер не підтримує цю функцію (наприклад, IE до версії 9 або Firefox перед версією 1.5), розгляньте можливість використання фільтр поліфіль від Mozilla.

Видалення елемента (ECMA-262 Edition 5 code aka oldstyle JS)

var value = 3

var arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(function(item) { 
    return item !== value
})

console.log(arr)
// [ 1, 2, 4, 5 ]

Видалення елемента (код ES2015)

let value = 3

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => item !== value)

console.log(arr)
// [ 1, 2, 4, 5 ]

ВАЖЛИВО ES2015 "() => {}" Синтаксис функції стрілки не підтримується в IE взагалі, Chrome до версії 45, Firefox до версії 22, Safari до версії 10. Для використання синтаксису ES2015 у старих браузерах можна використовувати BabelJS


Видалення кількох елементів (код ES2016)

Додатковою перевагою цього методу є те, що ви можете видалити кілька елементів

let forDeletion = [2, 3, 5]

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!

console.log(arr)
// [ 1, 4 ]

ВАЖЛИВО "функція масиву.включає (...)" не підтримується в IE взагалі, Chrome до версії 47, Firefox до версії 43, Safari до версії 9 і Edge до версії 14, так ось наповнення з Mozilla

Видалення кількох елементів (найсучасніший експериментальний JavaScript ES2018?)

// array-lib.js

export function remove(...forDeletion) {
    return this.filter(item => !forDeletion.includes(item))
}

// main.js

import { remove } from './array-lib.js'

let arr = [1, 2, 3, 4, 5, 3]

// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)

console.log(arr)
// [ 1, 4 ]

Спробуй сам у BabelJS :)

Посилання


678
2017-12-19 19:54



але іноді ми хочемо видалити елемент з вихідного масиву (не незмінного), наприклад масив, який використовується в директиві Angular 2 * ngFor - Ravinder Payal
Краще прийнятого рішення, оскільки він не вважає, що перевага має лише одне входження матчу і незмінність - Greg
Використання фільтра набагато краще, ніж використання сплайсинга. Занадто просто. - user3344977
filter повинен бути набагато повільним для великого масиву, хоча? - Nathan
Супер повільний метод. - highmaintenance


Залежить від того, чи хочете ви тримати пусте місце чи ні.

Якщо вам потрібен порожній слот, видаліть це добре:

delete array[ index ];

Якщо ви цього не зробите, ви повинні використовувати сплайсинг спосіб:

array.splice( index, 1 );

І якщо вам потрібна цінність цього елемента, ви можете просто зберегти елемент повернутого масиву:

var value = array.splice( index, 1 )[0];

У випадку, якщо ви хочете зробити це в певному порядку, ви можете використовувати array.pop() для останнього або array.shift() для першого (і обидва повертають значення об'єкта теж).

І якщо ви не знаєте індекс елемента, ви можете використовувати array.indexOf( item ) отримати його (в if() щоб отримати один товар або в while() щоб отримати їх усіх). array.indexOf( item ) повертає або індекс, або -1, якщо не знайдено.


359
2018-04-23 22:32



Варто це зауважити var value не зберігатиме видалене значення, але масив, що містить вилучене значення. - Jakub
delete це не правильний спосіб видалити елемент з масиву !! - Progo
Якщо ви хочете "порожнім слотом", скористайтеся array[index] = undefined;. Використовуючи delete знищить оптимізацію. - Bergi
@ Якуб дуже хороший коментар, тому що зрозуміти, що я втратив багато часу і думав, що код програми якимось чином порушений ... - Pascal


Друг мав проблеми в Internet Explorer 8і показав мені, що він зробив. Я сказав йому, що це неправильно, і він сказав мені, що він отримав відповідь тут. Поточна найефективніша відповідь не буде працювати у всіх браузерах (наприклад, Internet Explorer 8), і лише перша частина елемента буде видалена.

Видалити всі екземпляри з масиву

function remove(arr, item) {
    for (var i = arr.length; i--;) {
        if (arr[i] === item) {
            arr.splice(i, 1);
        }
    }
}

Він цитує через масив назад (оскільки показники та довжина будуть змінюватися після видалення елементів) і видаляє елемент, якщо він знайшовся. Він працює у всіх браузерах.


228
2017-08-10 19:21



@sroes це не повинно бути, тому що цикл починається з i = arr.length -1 або i-- що робить його таким же, як і максимальний індекс. arr.length це лише початкове значення для i. i-- завжди буде істина (і зменшити на 1 на кожній петлі оп), поки вона не буде рівною 0 (фальшиве значення), і цикл потім зупиниться. - gabeno
Друга функція досить неефективна. На кожній ітерації "indexOf" почне пошук з початку масиву. - Ujeenator
@AmberdeBlack, на колекції з більш ніж 1 появою позиція, набагато краще зателефонувати фільтр метод замість цього arr.filter(function (el) { return el !== item }), уникаючи необхідності мутувати масив кілька разів. Це споживає дещо більше пам'яті, але працює набагато ефективніше, оскільки потрібно менше роботи. - Eugene Kuzmenko
@AlJey, він доступний лише з IE9 +. Є ще шанс, що це не спрацює. - Ujeenator
Ця відповідь працювала для мене, тому що мені потрібно було вилучити кілька елементів, але не в будь-якому конкретному порядку. Зворотна прогреція циклу тут обробляє ідеальне видалення елементів з масиву. - mintedsky


Є два основні підходи:

  1. сплайс (): anArray.splice(index, 1);

  2. видалити: delete anArray[index];

Будьте обережні, коли ви використовуєте видалення для масиву. Це добре для видалення атрибутів об'єктів, але не так добре для масивів. Краще використовувати splice для масивів.

Майте на увазі, що коли ви використовуєте delete для масиву можна отримати неправильні результати для anArray.length. Іншими словами, delete буде видалити елемент, але не буде оновлювати значення властивості довжини.

Ви також можете розраховувати на наявність нумерації номерів індексів після використання видалення, наприклад ви могли б в кінцевому підсумку мати індекси 1,3,4,8,9,11 і довжини, як це було до використання видалити. У цьому випадку всі індексируются for петлі збігаються, оскільки індекси більше не є послідовними.

Якщо ви змушені користуватися delete чомусь, то ви повинні використовувати for each цикли, коли вам потрібно петлі за допомогою масивів. Насправді завжди уникайте використання індексованих для циклів, якщо це можливо. Таким чином, код буде більш надійним і менш схильним до проблем з індексами.


131
2017-12-21 11:32





Array.prototype.remByVal = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}
//Call like
[1, 2, 3, 4].remByVal(3);

Array.prototype.remByVal = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}

var rooms = ['hello', 'something']

rooms = rooms.remByVal('hello')

console.log(rooms)


104
2018-04-23 22:20



Я не великий шанувальник цього підходу. Якщо ви в кінцевому підсумку використовуєте різні бібліотеки або структури, вони можуть призвести до конфліктів між собою. - Charlie Kilian
Це також спрацювало, хоча я вирішив піти з функцією indexOf. Дякую за допомогу! - Walker
Погана ідея, дивіться цей пост: stackoverflow.com/questions/948358/array-prototype-problem - MMeah
Якщо ти робиш for in У масиві ви вже маєте проблему. - Zirak
Якщо ти зробиш for in У масивах у вас вже є більші проблеми. - Rainb