Как удалить определенный элемент из массива в JavaScript? - PullRequest
7275 голосов
/ 24 апреля 2011

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

Есть ли простой способ удалить определенный элемент из массива?Эквивалент чего-то вроде array.remove(number);.

Мне нужно использовать core JavaScript - нет фреймворки разрешены.

Ответы [ 79 ]

10454 голосов
/ 24 апреля 2011

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

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

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

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

1091 голосов
/ 24 апреля 2011

Я не знаю, как вы ожидаете 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];
927 голосов
/ 19 декабря 2013

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

  • Делайте это просто, интуитивно понятно и понятно (https://en.wikipedia.org/wiki/Occam%27s_razor)
  • Сделать его неизменным (исходный массив остается неизменным)
  • Делайте это со стандартными функциями JS, если ваш браузер их не поддерживает - используйте полифилл

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

Удаление элемента (код ECMA-262 Edition 5, также известный как 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 ]

ВАЖНО Функция "array.includes (...)" вообще не поддерживается в IE, 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:)

Ссылка

405 голосов
/ 24 апреля 2011

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

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

delete array[ index ];

Если вы этого не сделаете, выследует использовать метод splice :

array.splice( index, 1 );

И если вам нужно значение этого элемента, вы можете просто сохранить элемент возвращаемого массива:

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

InЕсли вы хотите сделать это в некотором порядке, вы можете использовать array.pop() для последнего или array.shift() для первого (и оба возвращают значение элемента тоже).

И если вы неНе знаете индекс предмета, вы можете использовать array.indexOf( item ), чтобы получить его (в if(), чтобы получить один предмет или в while(), чтобы получить их все).array.indexOf( item ) возвращает либо индекс, либо -1, если не найден.

256 голосов
/ 10 августа 2013

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

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

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

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

151 голосов
/ 21 декабря 2012

Существует два основных подхода:

  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, если это возможно. В этом случае код будет более надежным и менее подверженным проблемам с индексами.

127 голосов
/ 24 апреля 2011
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)
93 голосов
/ 19 сентября 2013

Нет необходимости использовать 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 раз медленнее, чем move .Даже если его улучшить, убрав вызов indexOf в splice , он работает намного хуже, чем move .

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
63 голосов
/ 02 мая 2014

Слишком стар, чтобы отвечать, но может кому-то помочь, предоставив предикат вместо значения.

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

Использование

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;
    }
};
59 голосов
/ 30 августа 2013

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

// 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 элементов. Не знаю почему, но я подтвердил, что оригинальная реализация Джона не имеет этой проблемы.

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