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

5099

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

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

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

задан Walker 24 апр. '11 в 1:17
источник

56 ответов

  • 1
  • 2
7584

Сначала найдите index элемента, который вы хотите удалить:

var array = [2, 5, 9];
var index = array.indexOf(5);

Примечание: поддержка браузера для indexOf ограничена; он не поддерживается в Internet Explorer 7 и 8.

Затем удалите его с помощью splice:

if (index > -1) {
    array.splice(index, 1);
}

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


Если вам нужен indexOf в неподдерживаемом браузере, попробуйте выполнить polyfill. Узнайте больше об этом polyfill здесь.

Array.prototype.indexOf || (Array.prototype.indexOf = function(d, e) {
    var a;
    if (null == this) throw new TypeError('"this" is null or not defined');
    var c = Object(this),
        b = c.length >>> 0;
    if (0 === b) return -1;
    a = +e || 0;
    Infinity === Math.abs(a) && (a = 0);
    if (a >= b) return -1;
    for (a = Math.max(0 <= a ? a : b - Math.abs(a), 0); a < b;) {
        if (a in c && c[a] === d) return a;
        a++
    }
    return -1
});
ответ дан Tom Wadley 24 апр. '11 в 1:23
источник
719

Я не знаю, как вы ожидаете, что 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];
ответ дан Peter Olson 24 апр. '11 в 1:20
источник
400

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

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

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

Извлечение элемента (код ECMA-262 Edition 5 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


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

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

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 версии, поэтому здесь polyfill из 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:)

Ссылка

ответ дан Ujeenator 19 дек. '13 в 22:54
источник
308

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

Если вам нужен пустой слот, удаление будет прекрасным:

delete array[ index ];

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

array.splice( index, 1 );

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

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

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

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

ответ дан xavierm02 24 апр. '11 в 1:32
источник
190

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

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

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

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

ответ дан Ben Lesh 10 авг. '13 в 22:21
источник
100

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

  • splice(): anArray.splice(index, 1);

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

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

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

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

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

ответ дан Sasa 21 дек. '12 в 14:32
источник
81

Самый простой способ:

var index = array.indexOf(item);
if(index != -1)
    array.splice( index, 1 );
ответ дан Nanego 02 дек. '17 в 20:42
80
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)
ответ дан Zirak 24 апр. '11 в 1:20
источник
61

Нет необходимости использовать 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
ответ дан slosd 19 сент. '13 в 4:53
источник
40

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

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

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

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;
    }
};
ответ дан amd 02 мая '14 в 15:00
источник
39

John Resig опубликовал хорошую реализацию:

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

ответ дан Roger 30 авг. '13 в 22:07
источник
38

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

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

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
ответ дан vatsal 30 мая '14 в 12:57
источник
37

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

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

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

ответ дан Salvador Dali 11 февр. '14 в 1:06
источник
27

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

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]

ответ дан Loupax 18 окт. '12 в 13:13
источник
24

Проверьте этот код. Он работает в каждом главном браузере .

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);
ответ дан Ekramul Hoque 02 апр. '13 в 13:56
источник
23

Вы можете использовать ES6.

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

Выход:

["1", "2", "4", "5", "6"]
ответ дан rajat44 04 окт. '16 в 11:07
источник
20

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

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']
ответ дан Chun Yang 25 авг. '15 в 22:34
источник
16

Я новичок в 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" ]

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

ответ дан sofiax 16 янв. '14 в 14:27
источник
16

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

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

this.array = this.array.filter(function(element, i) {
    return element.id !== idToRemove;
});
ответ дан flurdy 09 апр. '15 в 13:00
источник
13

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

const removeByIndex = (list, index) =>
  [
    ...list.slice(0, index),
    ...list.slice(index + 1)
  ];

Тогда:

removeByIndex([33,22,11,44],1) //=> [33,11,44]
ответ дан Abdennour TOUMI 07 окт. '16 в 22:42
источник
12

Более современный, 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, чтобы это было хорошо браузеры.

ответ дан bjfletcher 25 апр. '16 в 13:21
источник
12

Обновление: Этот метод рекомендуется использовать, только если вы не можете использовать 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]
ответ дан zykadelic 13 марта '13 в 12:28
источник
7

Я знаю, что уже есть много ответов, но многие из них, похоже, усложняют проблему. Вот простой, рекурсивный способ удаления всех экземпляров ключа - вызывает 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);
}
ответ дан slccsoccer28 03 февр. '14 в 18:41
источник
7

Удалить по индексу

Функция, возвращающая копию массива без элемента в индексе.

/**
* removeByIndex
* @param {Array} array
* @param {Number} index
*/
function removeByIndex(array, index){
    return array.filter(function(elem, _index){
        return index != _index;
    });
}
l = [1,3,4,5,6,7];
console.log(removeByIndex(l, 1));

$> [ 1, 4, 5, 6, 7 ]

Удалить по значению

Функция, возвращающая копию массива без значения.

/**
* removeByValue
* @param {Array} array
* @param {Number} value
*/
function removeByValue(array, value){
    return array.filter(function(elem, _index){
        return value != elem;
    });
}
l = [1,3,4,5,6,7];
console.log(removeByValue(l, 5));

$> [ 1, 3, 4, 6, 7]
ответ дан nsantana 12 мая '17 в 5:00
источник
6

Использовать jQuery InArray:

A = [1, 2, 3, 4, 5, 6];
A.splice($.inArray(3, A), 1);
//It will return A=[1, 2, 4, 5, 6]`   

Примечание: inArray вернет -1, если элемент не найден.

ответ дан Do Hoa Vinh 17 сент. '14 в 13:14
источник
6

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

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

ответ дан Jeff Noel 12 авг. '13 в 20:56
источник
5

Создать новый массив:

var my_array = new Array();

Добавить элементы в этот массив:

my_array.push("element1");

Функция indexOf (возвращает индекс или -1, если не найден):

var indexOf = function(needle) 
{
    if(typeof Array.prototype.indexOf === 'function') // newer browsers
    {
        indexOf = Array.prototype.indexOf;
    } 
    else // older browsers
    {
        indexOf = function(needle) 
        {
            var index = -1;

            for(var i = 0; i < this.length; i++) 
            {
                if(this[i] === needle) 
                {
                    index = i;
                    break;
                }
            }
            return index;
        };
    }

    return indexOf.call(this, needle);
};

Проверить индекс этого элемента (проверено с помощью firefox и IE8 +):

var index = indexOf.call(my_array, "element1");

Удалить 1 элемент, расположенный по индексу из массива

my_array.splice(index, 1);
ответ дан Enrico 07 авг. '13 в 15:57
источник
5

Я также столкнулся с ситуацией, когда мне пришлось удалить элемент из Array. .indexOf не работал в IE*, поэтому делился моим рабочим решением jQuery.inArray().

var index = jQuery.inArray(val,arr);
if (index > -1) {
    arr.splice(index, 1);
    //console.log(arr);
}
ответ дан NullPointer 08 окт. '13 в 13:09
источник
5

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

Представьте, что вы выполняете рекурсивный вызов и должны передавать массив с одним меньшим элементом, возможно, без текущего индексированного элемента. Или представьте, что вы выполняете другой рекурсивный вызов и должны передать массив с нажатым элементом.

В любом из этих случаев вы не можете сделать myRecursiveFunction(myArr.push(c)) или myRecursiveFunction(myArr.splice(i,1)). Первый идиот фактически передаст длину массива, а второй идиот передаст удаленный элемент в качестве параметра.

Итак, что я делаю на самом деле... Для удаления элемента массива и передачи результата в функцию в качестве параметра в то же время я делаю следующее:

myRecursiveFunction(myArr.slice(0,i).concat(a.slice(i+1)))

Когда дело доходит до того, что это глупо... Мне нравится,

myRecursiveFunction((myArr.push(c),myArr))

Я верю в правильный функциональный язык, метод, который мутирует вызываемый объект, должен возвращать ссылку на сам объект.

ответ дан Redu 07 мая '16 в 23:10
источник
5
  Array.prototype.removeItem = function(a) {
            for (i = 0; i < this.length; i++) {
                if (this[i] == a) {
                    for (i2 = i; i2 < this.length - 1; i2++) {
                        this[i2] = this[i2 + 1];
                    }
                    this.length = this.length - 1
                    return;
                }
            }
        }

    var recentMovies = ['Iron Man', 'Batman', 'Superman', 'Spiderman'];
    recentMovies.removeItem('Superman');
ответ дан Don Vincent Preziosi 26 сент. '13 в 3:12
источник
  • 1
  • 2

Ознакомьтесь с другими вопросами по меткам