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

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

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

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

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

56 ответов

  • 1
  • 2

Сначала найдите 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
});
7584
ответ дан Tom Wadley 24 апр. '11 в 1:23
источник поделиться

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

Отредактировано 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:)

Ссылка

400
ответ дан Ujeenator 19 дек. '13 в 22:54
источник поделиться

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

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

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

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

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

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

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

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

190
ответ дан Ben Lesh 10 авг. '13 в 22:21
источник поделиться

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

  • 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, когда вам нужно перебирать массивы. По сути дела, всегда избегайте использования индексированных для петель, если это возможно. Таким образом, код будет более надежным и менее подверженным проблемам с индексами.

100
ответ дан Sasa 21 дек. '12 в 14:32
источник поделиться

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

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

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

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

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

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

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

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 не имеет этой проблемы.

39
ответ дан Roger 30 авг. '13 в 22:07
источник поделиться

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

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

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

Вы можете сделать это легко с помощью метода 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

37
ответ дан Salvador Dali 11 февр. '14 в 1:06
источник поделиться

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

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]

27
ответ дан Loupax 18 окт. '12 в 13:13
источник поделиться

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

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

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

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

Выход:

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

Вы можете использовать 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']
20
ответ дан Chun Yang 25 авг. '15 в 22:34
источник поделиться

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

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

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

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

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

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

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

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

Тогда:

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

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

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

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

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

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

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

/**
* 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]
7
ответ дан nsantana 12 мая '17 в 5:00
источник поделиться

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

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

6
ответ дан Jeff Noel 12 авг. '13 в 20:56
источник поделиться

Использовать 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, если элемент не найден.

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

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

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

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

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);
5
ответ дан Enrico 07 авг. '13 в 15:57
источник поделиться
  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');
5
ответ дан Don Vincent Preziosi 26 сент. '13 в 3:12
источник поделиться

Я думаю, что многие из инструкций 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))

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

5
ответ дан Redu 07 мая '16 в 23:10
источник поделиться
  • 1
  • 2

Другие вопросы по меткам