javascript - элементов - удалить определенный элемент массива js




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

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

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

Я должен использовать базовый JavaScript - никакие рамки не разрешены.

https://code.i-harness.com


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

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

Затем :

removeByIndex([33,22,11,44],1) //=> [33,11,44]

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

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

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

Удаление элемента (ECMA-262 Edition 5 code 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

Удаление нескольких элементов (код 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

Удаление нескольких элементов (передовой экспериментальный 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 :)

Ссылка


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

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

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

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

Один из способов - использовать slice() :

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i-1).concat(items.slice(i, 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/ )


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

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

Выход :

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

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


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

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 filter


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

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]


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

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

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

Найдите 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 изменяет массив на месте и возвращает новый массив, содержащий удаленные элементы.

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

Если вам нужен 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
});

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

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

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

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

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. splice () : anArray.splice(index, 1);

  2. delete : delete anArray[index];

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

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

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

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


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

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


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

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

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

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

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

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

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] s в массиве?

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.


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

Основываясь на всех ответах, которые были в основном правильными, и с учетом лучших практических рекомендаций (особенно, не используя напрямую Array.prototype), я придумал приведенный ниже код:

function arrayWithout(arr, values) {
  var isArray = function(canBeArray) {
    if (Array.isArray) {
      return Array.isArray(canBeArray);
    }
    return Object.prototype.toString.call(canBeArray) === '[object Array]';
  };

  var excludedValues = (isArray(values)) ? values : [].slice.call(arguments, 1);
  var arrCopy = arr.slice(0);

  for (var i = arrCopy.length - 1; i >= 0; i--) {
    if (excludedValues.indexOf(arrCopy[i]) > -1) {
      arrCopy.splice(i, 1);
    }
  }

  return arrCopy;
}

Пересмотрев вышеприведенную функцию, несмотря на то, что она работает нормально, я понял, что может быть некоторое улучшение производительности. Также использование ES6 вместо ES5 - гораздо лучший подход. С этой целью это улучшенный код:

const arrayWithoutFastest = (() => {
  const isArray = canBeArray => ('isArray' in Array) 
    ? Array.isArray(canBeArray) 
    : Object.prototype.toString.call(canBeArray) === '[object Array]';

  let mapIncludes = (map, key) => map.has(key);
  let objectIncludes = (obj, key) => key in obj;
  let includes;

  function arrayWithoutFastest(arr, ...thisArgs) {
    let withoutValues = isArray(thisArgs[0]) ? thisArgs[0] : thisArgs;

    if (typeof Map !== 'undefined') {
      withoutValues = withoutValues.reduce((map, value) => map.set(value, value), new Map());
      includes = mapIncludes;
    } else {
      withoutValues = withoutValues.reduce((map, value) => { map[value] = value; return map; } , {}); 
      includes = objectIncludes;
    }

    const arrCopy = [];
    const length = arr.length;

    for (let i = 0; i < length; i++) {
      // If value is not in exclude list
      if (!includes(withoutValues, arr[i])) {
        arrCopy.push(arr[i]);
      }
    }

    return arrCopy;
  }

  return arrayWithoutFastest;  
})();

Как пользоваться:

const arr = [1,2,3,4,5,"name", false];

arrayWithoutFastest(arr, 1); // will return array [2,3,4,5,"name", false]
arrayWithoutFastest(arr, 'name'); // will return [2,3,4,5, false]
arrayWithoutFastest(arr, false); // will return [2,3,4,5]
arrayWithoutFastest(arr,[1,2]); // will return [3,4,5,"name", false];
arrayWithoutFastest(arr, {bar: "foo"}); // will return the same array (new copy)

В настоящее время я пишу сообщение в блоге, в котором я без проблем сравнивал несколько решений для Array и сравнивал время, которое требуется для запуска. Я обновлю этот ответ ссылкой, как только закончу этот пост. Просто, чтобы вы знали, я сравнил приведенное выше с lodash без, и в случае, если браузер поддерживает Map, он бьет lodash! Обратите внимание, что я не использую Array.prototype.indexOfили не Array.prototype.includesобертываю exlcudeValues ​​в a Mapили не Objectделает запрос быстрее! ( https://jsperf.com/array-without-benchmark-against-lodash )


У вас есть от 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);

Если вы хотите использовать несколько значений ex: - 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, 5 removed", newNumberArray);

Если вы хотите удалить значение массива в массиве ex: - [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);

включает поддерживаемый браузер - link


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

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




arrays