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

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

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

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

array.remove(number);

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

Ответов (25)

Решение

Найдите 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;
}
// Usage
console.log(removeItemOnce([2,5,9,1,5,8,5], 5))
console.log(removeItemAll([2,5,9,1,5,8,5], 5))

В TypeScript эти функции могут оставаться типобезопасными с параметром типа:

function removeItem<T>(arr: Array<T>, value: T): Array<T> { 
  const index = arr.indexOf(value);
  if (index > -1) {
    arr.splice(index, 1);
  }
  return arr;
}

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

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] .

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

Посмотрите этот код. Он работает во всех основных браузерах .

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

var array = [1,3,5,6,5,9,5,3,55]
var res = remove_item(array,5);
console.log(res)

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

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

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

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

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

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

Нет необходимости использовать 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

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

Выход - как и ожидалось. ["элемент1", "элемент1"]

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

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

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 .

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

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

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

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;
 },
};

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

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

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

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

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

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

Вы можете использовать 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']

Отредактировано: октябрь 2016 г.

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

В этом примере кода я использую функцию array.filter (...) для удаления нежелательных элементов из массива. Эта функция не изменяет исходный массив, а создает новый. Если ваш браузер не поддерживает эту функцию (например, Internet Explorer до версии 9 или Firefox до версии 1.5), рассмотрите возможность использования полифилла фильтра от 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 Syntax" когда-либо будет принято, вы сможете сделать это:

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

Ссылка

Вы можете использовать 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"]

Вот несколько способов удалить элемент из массива с помощью 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/ )

Я хочу ответить на основе 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]

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

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

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');

ИЛИ

var array = ['1','2','3','4','5','6'];
var newArray = array.filter(function(item){ return item !== '3' });

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

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)

Хорошо, например, у вас есть массив ниже:

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.

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

Сегодня (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, H растворы являются неизменяемыми.

Результаты для массива из 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). Вы можете выполнить тест на вашей машине здесь .

var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var log = (letter,array) => console.log(letter, array.join `,`);

function A(array) {
  var index = array.indexOf(5);
  delete array[index];
  log('A', array);
}

function B(array) {
  var index = array.indexOf(5);
  var arr = Array.from(array);
  arr.splice(index, 1)
  log('B', arr);
}

function C(array) {
  var index = array.indexOf(5);
  array.splice(index, 1);
  log('C', array);
}

function D(array) {
  var arr = array.filter(item => item !== 5)
  log('D', arr);
}

function E(array) {
  var index = array.indexOf(5);
  var arr = array.filter((item, i) => i !== index)
  log('E', arr);
}

function F(array) {
  var index = array.indexOf(5);
  var arr = array.slice(0, index).concat(array.slice(index + 1))
  log('F', arr);
}

function G(array) {
  var index = array.indexOf(5);
  var arr = [...array.slice(0, index), ...array.slice(index + 1)]
  log('G', arr);
}

function H(array) {
  var index = array.indexOf(5);
  var arr = array.slice(0);
  arr.splice(index, 1);
  log('H', arr);
}

A([...a]);
B([...a]);
C([...a]);
D([...a]);
E([...a]);
F([...a]);
G([...a]);
H([...a]);
This snippet only presents code used in performance tests - it does not perform tests itself.

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

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

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

  1. splice () :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 циклов. Таким образом код будет более надежным и менее подверженным проблемам с индексами.

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

Если вы делаете хотите пустой слот:

array[index] = undefined;

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

//To keep the original:
//oldArray = [...array];

//This modifies the array.
array.splice(index, 1);

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

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

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

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

Array.prototype.remove_by_value = 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)
].remove_by_value(3);

Array.prototype.remove_by_value = 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.remove_by_value('hello')

console.log(rooms)

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