Как я могу удалить определенный элемент из массива?


8300

У меня есть массив чисел, и я использую .push()метод для добавления элементов к нему.

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

Я ищу эквивалент чего-то вроде:

array.remove(number);

Я должен использовать основной JavaScript. Рамки не допускаются.

Ответы:


11902

Найдите indexэлемент массива, который вы хотите удалить indexOf, а затем удалите этот индекс splice.

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

const array = [2, 5, 9];

console.log(array);

const index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}

// array = [2, 9]
console.log(array); 

Второй параметр splice- это количество удаляемых элементов. Обратите внимание, что spliceизменяет массив на месте и возвращает новый массив, содержащий элементы, которые были удалены.


Для полноты здесь приведены функции. Первая функция удаляет только одно вхождение (т.е. удаляет первое совпадение 5с [2,5,9,1,5,8,5]), а вторая функция удаляет все вхождения:

function removeItemOnce(arr, value) { 
    var index = arr.indexOf(value);
    if (index > -1) {
        arr.splice(index, 1);
    }
    return arr;
}

function removeItemAll(arr, value) {
    var i = 0;
    while (i < arr.length) {
        if(arr[i] === value) {
            arr.splice(i, 1);
        } else {
            ++i;
        }
    }
    return arr;
}

15
@ Питер, да, возможно, ты прав. Эта статья объясняет больше и имеет обходной путь для несовместимых браузеров: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
Том Уодли

33
@AlexandreWiechersVaz Конечно, он сохраняет порядок, а если нет, то он будет абсолютно бесполезным
TheZ

15
Вы можете преодолеть проблему поддержки браузера IE, включив приведенный здесь

15
@AdrianP. array.indexOf(testValue)в пустом массиве будет -1, и если вы проверяете это, то нет соединения. Может быть, ответ изменился с тех пор.
UpTheCreek

13
IE 7, IE8, IE9, IE10 не поддерживаются самой Microsoft, почему веб-разработчики должны поддерживать эти старые браузеры? Просто покажите уведомление об обновлении браузера! support.microsoft.com/en-us/lifecycle/… ..
Лукас Лиезис

1269

Я не знаю, как вы ожидаете 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];

335
deleteнеправильный способ удалить элемент из массива!
Феликс Клинг

71
@FelixKling Зависит от того, работает ли он, если вы хотите, чтобы он array.hasOwnProperty(i)возвращался falseи возвращал элемент в этой позиции undefined. Но я признаю, что это не очень распространенная вещь, которую хочется делать.
Питер Олсон

88
deleteне обновляет длину массива и не стирает элемент, а только заменяет его специальным значением undefined.
diosney

34
@ diosney Я не знаю, что ты имеешь в виду, когда говоришь, что это не стирает элемент. Кроме того, он делает больше, чем просто заменяет значение в этом индексе undefined: он удаляет как индекс, так и значение из массива, то есть после delete array[0], "0" in arrayвозвращает false.
Питер Олсон

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

1207

Отредактировано в октябре 2016

  • Делайте это просто, интуитивно понятно и явно ( бритва Оккама )
  • Сделайте это неизменным (исходный массив остается неизменным)
  • Сделайте это с помощью стандартных функций JavaScript, если ваш браузер их не поддерживает - используйте polyfill

В этом примере кода я использую функцию «array.filter (...)» для удаления ненужных элементов из массива. Эта функция не меняет исходный массив и создает новый. Если ваш браузер не поддерживает эту функцию (например, Internet Explorer до версии 9 или Firefox до версии 1.5), рассмотрите возможность использования фильтра polyfill из Mozilla .

Удаление элемента (код ECMA-262 Edition 5, также известный как старый стиль JavaScript)

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 ]

Удаление элемента (код ECMAScript 6)

let value = 3

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

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

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

ВАЖНО ECMAScript 6 "() => {}" Синтаксис функции стрелок вообще не поддерживается в Internet Explorer, Chrome до 45 версии, Firefox до 22 версии и Safari до 10 версии. Для использования синтаксиса ECMAScript 6 в старых браузерах вы можете использовать BabelJS .


Удаление нескольких элементов (код ECMAScript 7)

Дополнительным преимуществом этого метода является то, что вы можете удалить несколько элементов

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 ]

ВАЖНО! Функция "array.includes (...)" вообще не поддерживается в Internet Explorer, Chrome до 47 версии, Firefox до 43 версии, Safari до 9 версии и Edge до 14 версии, так что здесь есть полифил из Mozilla .

Удаление нескольких элементов (возможно, в будущем)

Если предложение «Синтаксис This-Binding» будет принято, вы сможете сделать это:

// 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 :)

Ссылка


6
но иногда мы хотим удалить элемент из исходного массива (неизменяемого), например, массив, используемый в директиве Angular 2 * ngFor
Ravinder Payal

43
Лучше, чем принятое решение, потому что оно не предполагает единственного совпадения и предпочтительна неизменность
Грег

13
filterдолжно быть намного медленнее для большого массива, хотя?
Натан

3
Какой смысл неизменности упоминается, если вы использовали присваивание той же переменной в ваших примерах? :)
Mench

12
Это отличный ответ. Splice - это специализированная функция для мутации без фильтрации. filterможет иметь более низкую производительность, но это более безопасный и лучший код. Кроме того, вы можете фильтровать по индексу, указав второй аргумент в лямбду:arr.filter((x,i)=>i!==2)
Матфея

449

Это зависит от того, хотите ли вы оставить пустое место или нет.

Если вам нужен пустой слот, удаление возможно:

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, если не найден. 


25
deleteнеправильный способ удалить элемент из массива !!
Progo

16
Если вы хотите «очистить слот», используйте array[index] = undefined;. Использование deleteуничтожит оптимизацию.
Берги,

4
@Jakub очень хороший комментарий, потому что, чтобы понять, что я потерял много времени и думал, что мой код приложения как-то не работает ...
Паскаль

Последний абзац с объяснением того, что вы получаете от indexOf, был действительно полезен
A. D'Alfonso

277

У друга были проблемы в Internet Explorer 8 и он показал мне, что он сделал. Я сказал ему, что это неправильно, и он сказал мне, что получил ответ здесь. Текущий верхний ответ не будет работать во всех браузерах (например, Internet Explorer 8), и он будет удалять только первое вхождение элемента.

Удалить ВСЕ экземпляры из массива

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

Он перебирает массив в обратном направлении (поскольку индексы и длина изменяются при удалении элементов) и удаляет элемент, если он найден. Работает во всех браузерах.


11
@ sroes это не должно быть, потому что цикл начинается i = arr.length -1или i--делает его таким же, как индекс max. arr.lengthэто просто начальное значение для i. i--всегда будет правдивым (и уменьшаться на 1 при каждой операции цикла) до тех пор, пока оно не 0станет равным (ложное значение), и цикл затем остановится.
Гмадживу

1
Вторая функция довольно неэффективна. На каждой итерации «indexOf» будет начинать поиск с начала массива.
ujeenator

3
@AmberdeBlack, для коллекции с более чем 1 вхождением элемента , гораздо лучше вместо этого вызвать метод filterarr.filter(function (el) { return el !== item }) , избегая необходимости многократного изменения массива. Это потребляет немного больше памяти, но работает намного эффективнее, так как требуется меньше работы.
Евгений Кузьменко

1
@ AlJey, это доступно только из IE9 +. Есть шанс, что это не сработает.
ujeenator

1
Этот ответ работал для меня, потому что мне нужно было удалить несколько элементов, но не в каком-то определенном порядке. Обратная последовательность цикла for здесь отлично справляется с удалением элементов из массива.
mintedsky

172

Есть два основных подхода:

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

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

Будьте осторожны, когда вы используете delete для массива. Это хорошо для удаления атрибутов объектов, но не так хорошо для массивов. Лучше использовать spliceдля массивов.

Имейте в виду, что когда вы используете deleteмассив, вы можете получить неверные результаты anArray.length. Другими словами, deleteудалит элемент, но не обновит значение свойства length.

Вы также можете ожидать, что у вас будут дыры в индексах после использования delete, например, вы можете получить индексы 1, 3, 4, 8, 9 и 11 и длину, как это было до использования delete. В этом случае все проиндексированные forциклы будут аварийно завершены, поскольку индексы больше не являются последовательными.

Если вы вынуждены использовать deleteпо какой-то причине, то вы должны использовать for eachциклы, когда вам нужно перебрать массивы. На самом деле, всегда избегайте использования индексированных forциклов, если это возможно. Таким образом, код будет более устойчивым и менее подверженным проблемам с индексами.


144
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)


14
Я не большой поклонник такого подхода. Если вы в конечном итоге используете разные библиотеки или фреймворки, они могут конфликтовать друг с другом.
Чарли Килиан

10
Плохая идея, см. Этот пост: stackoverflow.com/questions/948358/array-prototype-problem
MMeah

10
Если вы делаете for inмассив, у вас уже есть проблема.
Зирак

2
если вы делаете for inна массивах, у вас уже есть большие проблемы.
Rainb

используйте Object.defineProperty stackoverflow.com/a/35518127/3779853 и все готово .
phil294

105

Там нет необходимости использовать indexOfили splice. Однако он работает лучше, если вы хотите удалить только одно вхождение элемента.

Найти и переместить (переместить):

function move(arr, val) {
  var j = 0;
  for (var i = 0, l = arr.length; i < l; i++) {
    if (arr[i] !== val) {
      arr[j++] = arr[i];
    }
  }
  arr.length = j;
}

Используйте indexOfи splice(indexof):

function indexof(arr, val) {
  var i;
  while ((i = arr.indexOf(val)) != -1) {
    arr.splice(i, 1);
  }
}

Использовать только splice(соединение):

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

Время выполнения на nodejs для массива с 1000 элементов (в среднем более 10000 запусков):

indexof примерно в 10 раз медленнее, чем двигаться . Даже если его улучшить, удалив вызов indexOfв сплайсинге, он работает намного хуже, чем перемещение .

Remove all occurrences:
    move 0.0048 ms
    indexof 0.0463 ms
    splice 0.0359 ms

Remove first occurrence:
    move_one 0.0041 ms
    indexof_one 0.0021 ms

5
Похоже, представленный здесь метод 'move' должен работать во всех браузерах, а также избегать создания дополнительного массива; большинство других решений здесь имеют одну или обе из этих проблем. Я думаю, что этот заслуживает гораздо больше голосов, даже если он не выглядит "красиво".
sockmonk

73

Это обеспечивает предикат вместо значения.

ПРИМЕЧАНИЕ: он обновит данный массив и вернет затронутые строки.

Применение

var removed = helper.removeOne(arr, row => row.id === 5 );

var removed = helper.remove(arr, row => row.name.startsWith('BMW'));

Определение

var helper = {

    // Remove and return the first occurrence

    removeOne: function(array, predicate) {
        for (var i = 0; i < array.length; i++) {
            if (predicate(array[i])) {
                return array.splice(i, 1);
            }
        }
    },

    // Remove and return all occurrences

    remove: function(array, predicate) {
        var removed = [];

        for (var i = 0; i < array.length;) {

            if (predicate(array[i])) {
                removed.push(array.splice(i, 1));
                continue;
            }
            i++;
        }
        return removed;
    }
};

Я не знаю, что вам нужна проверка -1 (я> -1). Кроме того, я думаю, что эти функции действуют скорее как фильтр, чем как удаление. Если вы передадите row.id === 5, это приведет к массиву только с идентификатором 5, поэтому он выполняет противоположное удаление. Это будет хорошо выглядеть в ES2015: var result = ArrayHelper.remove (myArray, row => row.id === 5);
Что будет круто

@WhatWouldBeCool этой функции изменения исходного массива и возвращает удаленный элемент вместо копирования результата в новый массив
драмы

68

Вы можете сделать это легко с помощью метода фильтра :

function remove(arrOriginal, elementToRemove){
    return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log(remove([1, 2, 1, 0, 3, 1, 4], 1));

Это удаляет все элементы из массива, а также работает быстрее, чем комбинация sliceи indexOf.


3
У вас есть источник, что это быстрее?
user3711421

2
Хорошее решение. Но, как вы отметили, но важно сделать лысый, он не даст тот же результат, что и slice и indexOf, так как он удалит все вхождения 1
user3711421

1
@ user3711421 это потому, что просто slice и indexOf не делают то, что он хочет, «удалить определенный элемент». Он удаляет элемент только один раз, этот элемент удаляется независимо от того, сколько у вас их
Сальвадор Дали

66

Джон Резиг опубликовал хорошую реализацию :

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

Если вы не хотите расширять глобальный объект, вместо этого вы можете сделать что-то вроде следующего:

// Array Remove - By John Resig (MIT Licensed)
Array.remove = function(array, from, to) {
    var rest = array.slice((to || from) + 1 || array.length);
    array.length = from < 0 ? array.length + from : from;
    return array.push.apply(array, rest);
};

Но главная причина, по которой я публикую это, состоит в том, чтобы предостеречь пользователей от альтернативной реализации, предложенной в комментариях на этой странице (14 декабря 2007 г.):

Array.prototype.remove = function(from, to){
  this.splice(from, (to=[0,from||1,++to-from][arguments.length])<0?this.length+to:to);
  return this.length;
};

Поначалу кажется, что это хорошо работает, но через болезненный процесс, который я обнаружил, он терпит неудачу при попытке удалить второй или последний элемент в массиве. Например, если у вас есть массив из 10 элементов, и вы пытаетесь удалить 9-й элемент следующим образом:

myArray.remove(8);

Вы получите массив из 8 элементов. Не знаю почему, но я подтвердил, что оригинальная реализация Джона не имеет этой проблемы.


Только что стало известно на нелегком пути , почему это идея хорошо использовать Object.prototype.hasOwnPropertyвсегда ¬¬
Дави Fiamenghi

64

Underscore.js можно использовать для решения проблем с несколькими браузерами. Он использует встроенные методы браузера, если таковые имеются. Если они отсутствуют, как в случае более старых версий Internet Explorer, он использует свои собственные пользовательские методы.

Простой пример удаления элементов из массива (с сайта):

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]

Несмотря на элегантность и лаконичность, OP четко упомянул только ядро ​​JS
EigenFool

64

Вы можете использовать ES6. Например, чтобы удалить значение «3» в этом случае:

var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
console.log(newArray);

Вывод :

["1", "2", "4", "5", "6"]

4
Этот ответ хорош, потому что он создает копию исходного массива, а не изменяет оригинал напрямую.
Клаудио Холанда

Примечание. Array.prototype.filter - это ECMAScript 5.1 (без IE8). для более конкретных решений: stackoverflow.com/a/54390552/8958729
Чанг

54

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

var my_array = [1, 2, 3, 4, 5, 6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));

Это должно отобразить [1, 2, 3, 4, 6].


45

Проверьте этот код. Это работает в любом крупном браузере .

remove_item = function (arr, value) {
    var b = '';
    for (b in arr) {
        if (arr[b] === value) {
            arr.splice(b, 1);
            break;
        }
    }
    return arr;
}

Вызвать эту функцию

remove_item(array,value);

4
@RolandIllig За исключением использования for in-loop и того факта, что сценарий можно было остановить раньше, возвращая результат из цикла напрямую. Прогнозы разумны;)
yckart

1
Это отличный подход для небольших массивов. Он работает в любом браузере, использует минимальный и интуитивно понятный код, без каких-либо дополнительных сложных каркасов, шайб или поли-заливок.
Бежор

Я должен также повторить комментарий yckart, который for( i = 0; i < arr.length; i++ )был бы лучшим подходом, поскольку он сохраняет точные индексы в зависимости от того, в каком порядке браузер решит хранить элементы (с for in). Это также позволяет вам получить индекс массива значения, если вам это нужно.
Бежор

41

Вы можете использовать lodash _.pull (массив мутирования), _.pullAt (массив мутирования) или _.without (не мутирует массив),

var array1 = ['a', 'b', 'c', 'd']
_.pull(array1, 'c')
console.log(array1) // ['a', 'b', 'd']

var array2 = ['e', 'f', 'g', 'h']
_.pullAt(array2, 0)
console.log(array2) // ['f', 'g', 'h']

var array3 = ['i', 'j', 'k', 'l']
var newArray = _.without(array3, 'i') // ['j', 'k', 'l']
console.log(array3) // ['i', 'j', 'k', 'l']

2
Это не основной JS, как запросил OP, не так ли?
какой-то не-дескриптор-пользователь

12
@ some-non-descript-user Вы правы. Но многие пользователи, подобные мне, приходят сюда в поисках общего ответа, а не только для ОП.
Чунь Ян

@ChunYang Вы абсолютно правы. Я уже использую lodash, почему бы просто не использовать его, если это экономит время.
Int-I

38

ES6 & без мутации: (октябрь 2016 г.)

const removeByIndex = (list, index) =>
      [
        ...list.slice(0, index),
        ...list.slice(index + 1)
      ];
         
output = removeByIndex([33,22,11,44],1) //=> [33,11,44]
      
console.log(output)


Почему бы просто не использовать filterтогда? array.filter((_, index) => index !== removedIndex);,
user4642212

@ user4642212 ты прав! Кроме того, мне понравилось подчеркивание стиля
Голанга

36

Удаление определенного элемента / строки из массива может быть сделано в одну строку:

theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);

где:

theArray : массив, из которого вы хотите удалить что-то конкретное

stringToRemoveFromArray : строка, которую вы хотите удалить, а 1 - это количество элементов, которые вы хотите удалить.

ПРИМЕЧАНИЕ . Если строка «stringToRemoveFromArray» не находится в массиве, это приведет к удалению последнего элемента массива.

Хорошей практикой является проверка наличия элемента в вашем массиве перед его удалением.

if (theArray.indexOf("stringToRemoveFromArray") >= 0){
   theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}

Если у вас есть доступ к более новым версиям Ecmascript на компьютерах вашего клиента (ВНИМАНИЕ, может не работать на старых станциях):

var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');

Где «3» - это значение, которое вы хотите удалить из массива. Массив станет:['1','2','4','5','6']


Это ответ, который работал для меня, когда я пытался обновить массив, основываясь на переключении переключателей.
jdavid05

4
Осторожно, если "stringToRemoveFromArray"в массиве не находится ваш, это удалит последний элемент массива.
Fusion

35

Вот несколько способов удалить элемент из массива с помощью JavaScript .

Все описанные методы не изменяют исходный массив , а создают новый.

Если вы знаете индекс предмета

Предположим, у вас есть массив, и вы хотите удалить элемент в позиции i.

Одним из методов является использование slice():

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i).concat(items.slice(i+1, items.length))

console.log(filteredItems)

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

Если вы знаете значение

В этом случае один хороший вариант - использовать filter(), который предлагает более декларативный подход:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)

console.log(filteredItems)

Это использует функции стрелки ES6. Вы можете использовать традиционные функции для поддержки старых браузеров:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
  return item !== valueToRemove
})

console.log(filteredItems)

или вы можете использовать Babel и перенести код ES6 обратно в ES5, чтобы сделать его более удобным для старых браузеров, и в то же время написать современный JavaScript в своем коде.

Удаление нескольких предметов

Что если вместо одного элемента вы хотите удалить много элементов?

Давайте найдем самое простое решение.

По индексу

Вы можете просто создать функцию и удалить элементы последовательно:

const items = ['a', 'b', 'c', 'd', 'e', 'f']

const removeItem = (items, i) =>
  items.slice(0, i-1).concat(items.slice(i, items.length))

let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]

console.log(filteredItems)

По значению

Вы можете искать включение внутри функции обратного вызова:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]

console.log(filteredItems)

Избегайте мутации исходного массива

splice()(не путать с slice()) изменяет исходный массив, и его следует избегать.

(первоначально размещено на https://flaviocopes.com/how-to-remove-item-from-array/ )


34

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

var num = [1, 2, 3, 4, 5];

И мы хотим удалить номер 4. Вы можете просто использовать следующий код:

num.splice(num.indexOf(4), 1); // num will be [1, 2, 3, 5];

Если вы повторно используете эту функцию, вы пишете функцию многократного использования, которая будет прикреплена к встроенной функции массива, как показано ниже:

Array.prototype.remove = Array.prototype.remove || function(x) {
  const i = this.indexOf(x);
  if(i===-1)
      return;
  this.splice(i, 1); // num.remove(5) === [1, 2, 3];
}

Но как насчет того, чтобы вместо этого у вас был массив ниже с несколькими [5] в массиве?

var num = [5, 6, 5, 4, 5, 1, 5];

Нам нужен цикл, чтобы проверить их все, но более простой и эффективный способ - использовать встроенные функции JavaScript, поэтому мы пишем функцию, которая использует фильтр, как показано ниже:

const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) // Return [1, 2, 3, 4, 6]

Также есть сторонние библиотеки, которые помогут вам в этом, например, Lodash или Underscore. Для получения дополнительной информации смотрите lodash _.pull, _.pullAt или _.without.


Есть небольшая опечатка. Пожалуйста исправьте. this.splice(num.indexOf(x), 1);=>this.splice(this.indexOf(x), 1);
TheGwa

Пожалуйста, не увеличивайте встроенные модули (присоединяйте функции к Array.prototype) в JavaScript. Это широко считается плохой практикой.
aikeru

Я согласен, что это не лучшая вещь в мире, но как в этом случае передать ее функции?
Алиреза

Вы должны проверить индекс. Если index = -1, сплайс (-1,1) удалит последний элемент
Ричард Чен

29

Я довольно новичок в JavaScript и мне нужна эта функциональность. Я просто написал это:

function removeFromArray(array, item, index) {
  while((index = array.indexOf(item)) > -1) {
    array.splice(index, 1);
  }
}

Тогда, когда я хочу использовать это:

//Set-up some dummy data
var dummyObj = {name:"meow"};
var dummyArray = [dummyObj, "item1", "item1", "item2"];

//Remove the dummy data
removeFromArray(dummyArray, dummyObj);
removeFromArray(dummyArray, "item2");

Выход - как и ожидалось. ["item1", "item1"]

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


1
Это будет иметь ужасное поведение, если ваш массив очень длинный и в нем есть несколько экземпляров элемента. Метод indexOf массива будет начинаться каждый раз с начала, поэтому ваша стоимость будет O (n ^ 2).
Заг


27

Если у вас есть сложные объекты в массиве, вы можете использовать фильтры? В ситуациях, когда $ .inArray или array.splice не так просты в использовании. Особенно если объекты, возможно, мелкие в массиве.

Например, если у вас есть объект с полем Id, и вы хотите удалить объект из массива:

this.array = this.array.filter(function(element, i) {
    return element.id !== idToRemove;
});

Вот как мне нравится это делать. Используя функцию стрелки это может быть однострочник. Мне интересно о производительности. Также ничего не стоит, что это заменяет массив. Любой код со ссылкой на старый массив не заметит изменения.
Joeytwiddle

27

Я хочу ответить на основе ECMAScript 6 . Предположим, у вас есть массив, как показано ниже:

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

Если вы хотите удалить по специальному индексу вроде 2, напишите следующий код:

arr.splice(2, 1); //=> arr became [1,2,4]

Но если вы хотите удалить специальный элемент, например, 3и не знаете его индекс, сделайте следующее:

arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]

Подсказка : пожалуйста, используйте функцию стрелки для обратного вызова фильтра, если вы не получите пустой массив.


25

Обновление: этот метод рекомендуется, только если вы не можете использовать ECMAScript 2015 (ранее известный как ES6). Если вы можете использовать его, другие ответы здесь обеспечивают более аккуратные реализации.


Эта суть здесь решит вашу проблему, а также удалит все вхождения аргумента вместо 1 (или указанного значения).

Array.prototype.destroy = function(obj){
    // Return null if no objects were found and removed
    var destroyed = null;

    for(var i = 0; i < this.length; i++){

        // Use while-loop to find adjacent equal objects
        while(this[i] === obj){

            // Remove this[i] and store it within destroyed
            destroyed = this.splice(i, 1)[0];
        }
    }

    return destroyed;
}

Применение:

var x = [1, 2, 3, 3, true, false, undefined, false];

x.destroy(3);         // => 3
x.destroy(false);     // => false
x;                    // => [1, 2, true, undefined]

x.destroy(true);      // => true
x.destroy(undefined); // => undefined
x;                    // => [1, 2]

x.destroy(3);         // => null
x;                    // => [1, 2]

25

Представление

Сегодня (2019-12-09) я провожу тесты производительности на macOS v10.13.6 (High Sierra) для выбранных решений. Я показываю delete(A), но я не использую его по сравнению с другими методами, потому что он оставил пустое место в массиве.

Выводы

  • самое быстрое решение - array.splice(C) (за исключением Safari для небольших массивов, где он второй раз)
  • для больших массивов array.slice+splice(H) - самое быстрое неизменное решение для Firefox и Safari; Array.from(B) самый быстрый в Chrome
  • изменяемые решения обычно в 1,5-6 раз быстрее, чем неизменяемые
  • для небольших таблиц в Safari неожиданно изменяемое решение (C) медленнее, чем неизменяемое решение (G)

подробности

В тестах я удаляю средний элемент из массива разными способами. A, C решения на месте. В, D, Е, F, G, Н растворы являются неизменяемыми.

Результаты для массива из 10 элементов

Введите описание изображения здесь

В Chrome array.splice(C) - самое быстрое решение на месте. array.filter(D) , является самым непреложным решением. Самый медленный - array.slice(F). Вы можете выполнить тест на вашей машине здесь .

Результаты для массива с 1.000.000 элементов

Введите описание изображения здесь

В Chrome array.splice(C) - самое быстрое решение на месте ( delete(C) очень быстро аналогично - но оно оставило пустую ячейку в массиве (поэтому не выполняет «полное удаление»)). array.slice-splice(Н) является самым непреложным решением. Самый медленный - array.filter(D и E). Вы можете выполнить тест на вашей машине здесь .

Сравнение для браузеров: Chrome v78.0.0, Safari v13.0.4 и Firefox v71.0.0

Введите описание изображения здесь


24

Вы никогда не должны изменять свой массив. Как это против функционального шаблона программирования. Вы можете создать новый массив без ссылки на массив, для которого вы хотите изменить данные, используя метод ECMAScript 6 filter;

var myArray = [1, 2, 3, 4, 5, 6];

Предположим, вы хотите удалить 5из массива, вы можете просто сделать это так:

myArray = myArray.filter(value => value !== 5);

Это даст вам новый массив без значения, которое вы хотите удалить. Таким образом, результат будет:

 [1, 2, 3, 4, 6]; // 5 has been removed from this array

Для дальнейшего понимания вы можете прочитать документацию MDN на Array.filter .


21

Более современный подход ECMAScript 2015 (ранее известный как Harmony или ES 6). Данный:

const items = [1, 2, 3, 4];
const index = 2;

Затем:

items.filter((x, i) => i !== index);

Уступая:

[1, 2, 4]

Вы можете использовать Babel и службу polyfill, чтобы гарантировать, что это хорошо поддерживается во всех браузерах.


4
Обратите внимание, что .filterвозвращается новый массив, который не совсем совпадает с удалением элемента из того же массива. Преимущество этого подхода заключается в том, что вы можете объединять методы массива вместе. Например:[1,2,3].filter(n => n%2).map(n => n*n) === [ 1, 9 ]
CodeOcelot

Отлично, если у меня есть 600К элементов в массиве и я хочу удалить первые 50К, вы можете себе представить эту медлительность? Это не решение, нужна функция, которая просто удаляет элементы и ничего не возвращает.
dev1223

@Seraph Для этого вы, вероятно, захотите использовать spliceили slice.
bjfletcher

@bjfletcher Это еще лучше, в процессе удаления, просто выделите 50К элементов и бросьте их куда-нибудь. (с ломтиками 550К элементов, но не выбрасывая их из окна).
dev1223

Я бы предпочел ответ bjfletcher, который может быть таким же коротким, как и items= items.filter(x=>x!=3). Кроме того, ОП не указывал никаких требований к большому набору данных.
RunSun

21

У вас есть от 1 до 9 в массиве, и вы хотите удалить 5. Используйте следующий код:

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return m !== 5;
});

console.log("new Array, 5 removed", newNumberArray);


Если вы хотите несколько значений. Пример: - 1,7,8

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return (m !== 1) && (m !== 7) && (m !== 8);
});

console.log("new Array, 1,7 and 8 removed", newNumberArray);


Если вы хотите удалить значение массива в массиве. Пример: [3,4,5]

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var removebleArray = [3,4,5];

var newNumberArray = numberArray.filter(m => {
    return !removebleArray.includes(m);
});

console.log("new Array, [3,4,5] removed", newNumberArray);

Включает в себя поддерживаемый браузер по ссылке .


19

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

Автономная функция

function removeAll(array, key){
    var index = array.indexOf(key);

    if(index === -1) return;

    array.splice(index, 1);
    removeAll(array,key);
}

Метод прототипа

Array.prototype.removeAll = function(key){
    var index = this.indexOf(key);

    if(index === -1) return;

    this.splice(index, 1);
    this.removeAll(key);
}

Просто обратите внимание, что 1 предостережение при использовании этого метода может привести к переполнению стека. Если вы не работаете с массивными массивами, у вас не должно быть проблем.
wharding28

Но почему возврат в середине? Это фактически заявление Goto.
Питер Мортенсен

18

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

var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];

/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
    if (myArray[i] == myElement) myArray.splice(i, 1);
}

Live Demo

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.