Como faço para remover um elemento particular de uma matriz em JavaScript?


14 Answers

Eu não sei como você está esperando array.remove(int) se comportar. Há três possibilidades que posso pensar que você pode estar querendo.

Para remover um elemento de uma matriz em um índice i :

array.splice(i, 1);

Se você quiser remover todos os elementos com o number do valor da matriz:

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

Se você quiser apenas fazer com que o elemento no índice i não exista mais, mas você não quer que os índices dos outros elementos sejam alterados:

delete array[i];
Question

Eu tenho uma matriz de inteiros e estou usando o método .push() para adicionar elementos a ele.

Existe uma maneira simples de remover um elemento específico de uma matriz? O equivalente a algo como array.remove(int); .

Eu tenho que usar o núcleo do JavaScript - nenhum framework é permitido.




Atualização: Este método é recomendado somente se você não puder usar o ECMAScript 2015 (anteriormente conhecido como ES6). Se você puder usá-lo, outras respostas aqui fornecem implementações muito mais simples.

Essa essência aqui resolverá seu problema e também excluirá todas as ocorrências do argumento em vez de apenas 1 (ou um valor especificado).

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

Uso:

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]



Depende se você quer manter um local vazio ou não.

Se você quer um slot vazio, delete está bem:

delete array[ index ];

Se você não fizer isso, você deve usar o método splice :

array.splice( index, 1 );

E se você precisar do valor desse item, você pode apenas armazenar o elemento da matriz retornada:

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

Caso você queira fazer isso em alguma ordem, você pode usar array.pop() para o último ou array.shift() para o primeiro (e ambos retornam o valor do item também).

E se você não sabe o índice do item, você pode usar array.indexOf( item ) para obtê-lo (em um if() para obter um item ou em um while() para obter todos eles). array.indexOf( item ) retorna o índice ou -1 se não for encontrado.




Sou novo em JavaScript e precisava dessa funcionalidade. Eu simplesmente escrevi isso:

function removeFromArray(array, item, index) {
  while((index = array.indexOf(item)) > -1) {
    array.splice(index, 1);
  }
}

Então quando eu quiser usá-lo:

//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");

Saída - como esperado. ["item1", "item1"]

Você pode ter necessidades diferentes de mim, então você pode facilmente modificá-lo para se adequar a elas. Espero que isso ajude alguém.




Com base em todas as respostas que estavam corretas e levando em consideração as melhores práticas sugeridas (especialmente não usando o Array.prototype diretamente), eu criei o código abaixo:

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

Revendo a função acima, apesar do fato de que funciona bem, percebi que poderia haver alguma melhora no desempenho. Também usar ES6 em vez de ES5 é uma abordagem muito melhor. Para esse fim, esse é o código aprimorado:

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;  
})();

Como usar:

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)

No momento, estou escrevendo um post de blog no qual testei várias soluções para o Array sem problemas e comparei o tempo necessário para executá-lo. Eu atualizarei esta resposta com o link assim que terminar esse post. Só para você saber, eu comparei o anterior com o da lodash sem e no caso do navegador suporta Map, ele bate lodash! Note que eu não estou usando Array.prototype.indexOfou Array.prototype.includesenvolvendo os exlcudeValues ​​em um Mapou Objectfaz consultas mais rápidas! ( https://jsperf.com/array-without-benchmark-against-lodash )




Existem duas abordagens principais:

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

  2. delete : delete anArray[index];

Tenha cuidado ao usar excluir para uma matriz. É bom para excluir atributos de objetos, mas não tão bons para matrizes. É melhor usar splice para matrizes.

Tenha em mente que quando você usa delete para um array, você pode obter resultados errados para anArray.length . Em outras palavras, delete removeria o elemento, mas não atualizaria o valor da propriedade length.

Você também pode esperar ter buracos nos números de índice depois de usar delete, por exemplo, você pode acabar tendo índices 1,3,4,8,9,11 e length como era antes de usar delete. Nesse caso, todos os loops indexados falharão, já que os índices não são mais sequenciais.

Se você for forçado a usar o delete por algum motivo, então você deve usar for each loop quando precisar fazer um loop por arrays. De fato, sempre evite usar loops indexados, se possível. Dessa forma, o código seria mais robusto e menos propenso a problemas com índices.




Não há necessidade de usar indexOf ou splice . No entanto, ele funciona melhor se você quiser apenas remover uma ocorrência de um elemento.

Encontre e mova (mova):

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

Use indexOf e splice (indexof):

function indexof(arr, val) {
  var i;
  while ((i = arr.indexOf(val)) != -1) {
    arr.splice(i, 1);
  }
}

Use apenas splice (emenda):

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

Tempos de execução em nodejs para matriz com 1000 elementos (média acima de 10000 execuções):

indexof é aproximadamente 10x mais lento que o movimento . Mesmo se melhorado, removendo a chamada para indexOf na emenda, ele executa muito pior do que mover .

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



Você pode usar lodash _.pull (matriz mutate), _.pullAt (matriz mutate) ou _.without (não _.without array),

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



Você pode usar o ES6.

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

Saída:

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



John Resig postou uma boa implementação :

// 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);
};

Se você não quiser estender um objeto global, poderá fazer algo como o seguinte:

// 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);
};

Mas a principal razão pela qual estou postando isso é alertar os usuários contra a implementação alternativa sugerida nos comentários nessa página (14 de dezembro de 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;
};

Parece funcionar bem no começo, mas através de um processo doloroso eu descobri que ele falha ao tentar remover o segundo para o último elemento em uma matriz. Por exemplo, se você tiver uma matriz de 10 elementos e tentar remover o 9º elemento com isto:

myArray.remove(8);

Você acaba com uma matriz de 8 elementos. Não sei porque, mas eu confirmei que a implementação original de John não tem esse problema.




Aqui estão algumas maneiras de remover um item de uma matriz usando JavaScript .

Todo o método descrito não altera o array original e cria um novo.

Se você conhece o índice de um item

Suponha que você tenha uma matriz e deseje remover um item na posição i .

Um método é usar 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() cria um novo array com os índices que recebe. Nós simplesmente criamos uma nova matriz, do início ao índice que queremos remover, e concatenamos outra matriz da primeira posição após a que removemos até o final da matriz.

Se você conhece o valor

Nesse caso, uma boa opção é usar filter() , que oferece uma abordagem mais declarativa :

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)

console.log(filteredItems)

Isso usa as funções de seta do ES6. Você pode usar as funções tradicionais para suportar navegadores mais antigos:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
  return item !== valueToRemove
})

console.log(filteredItems)

ou você pode usar o Babel e transpilar o código ES6 de volta para o ES5 para torná-lo mais digerível para navegadores antigos, e ainda escrever JavaScript moderno em seu código.

Removendo vários itens

E se, em vez de um único item, você quiser remover muitos itens?

Vamos encontrar a solução mais simples.

Por índice

Você pode apenas criar uma função e remover itens em série:

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)

Por valor

Você pode procurar por inclusão dentro da função de retorno de chamada:

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)

Evite mudar o array original

splice() (não deve ser confundido com slice() ) muta a matriz original e deve ser evitado.

(originalmente publicado em https://flaviocopes.com/how-to-remove-item-from-array/ )




Você nunca deve transformar seu array em array. Como isso é contra o padrão de programação funcional. O que você pode fazer é criar uma nova matriz sem fazer referência à matriz que você deseja alterar os dados usando o filter método es6;

const items = [1, 2, 3, 4];
const index = 2;

Suponha que você queira remover 5 da matriz, você pode simplesmente fazer assim.

items.filter((x, i) => i !== index);

Isso fornecerá uma nova matriz sem o valor que você deseja remover. Então o resultado será

[1, 2, 4]

Para entender melhor, você pode ler a documentação do MDN em Array.filter filter




Você pode fazer isso facilmente com o método de filter :

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

Isso remove todos os elementos da matriz e também funciona mais rápido do que a combinação de fatia e indexOf




Você tem 1 a 9 array e você quer remover 5 use abaixo do código.

var my_array = new Array();

Se você quiser um valor múltiplo ex: - 1,7,8

my_array.push("element1");

Se você quiser remover o valor da matriz na matriz ex: - [3,4,5]

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

inclui navegador suportado é link




Eu tenho outra boa solução para remover de uma matriz:

var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

filter






Related