Como posso remover um item específico de uma matriz?


8297

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

Existe uma maneira simples de remover um elemento específico de uma matriz?

Estou procurando o equivalente a algo como:

array.remove(number);

Eu tenho que usar o JavaScript principal . Estruturas não são permitidas.

Respostas:


11892

Encontre o indexelemento da matriz que você deseja remover usando indexOfe remova esse índice com splice.

O método splice () altera o conteúdo de uma matriz removendo os elementos existentes e / ou adicionando novos elementos.

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

O segundo parâmetro de spliceé o número de elementos a serem removidos. Observe que splicemodifica a matriz no local e retorna uma nova matriz contendo os elementos que foram removidos.


Por motivos de integridade, aqui estão as funções. Primeiro função remove ocorrência única único (isto é, a remoção do primeiro jogo 5de [2,5,9,1,5,8,5]), enquanto a segunda função remove todas as ocorrências:

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

15
@ Peter, sim, você pode estar certo. Este artigo explica mais e tem uma solução alternativa para navegadores incompatíveis: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
Tom Wadley

33
@AlexandreWiechersVaz Claro que preserva a ordem, se não o fizesse, seria absolutamente inútil #
TheZ

15
Você pode superar o problema de suporte ao navegador IE incluindo o código fornecido aqui #

15
@AdrianP. array.indexOf(testValue)na matriz vazia será -1, e se você estiver testando isso, não haverá emenda. Talvez a resposta tenha mudado desde então.
UpTheCreek

13
O IE 7, IE8, IE9, IE10 não é suportado pela própria Microsoft. Por que os desenvolvedores da Web suportam esses navegadores antigos? Basta mostrar uma notificação sobre a atualização do navegador! support.microsoft.com/en-us/lifecycle/…
Lukas Liesis

1268

Não sei como você espera array.remove(int)se comportar. Existem três possibilidades em que posso pensar que você pode querer.

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

array.splice(i, 1);

Se você deseja remover todos os elementos com valor numberda matriz:

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

Se você apenas deseja que o elemento no índice inão exista mais, mas não deseja que os índices dos outros elementos sejam alterados:

delete array[i];

335
deletenão é a maneira correta de remover um elemento de uma matriz!
Felix Kling 27/01

71
@FelixKling Depende, funciona se você quiser fazer com que ele array.hasOwnProperty(i)retorne falsee faça com que o elemento nessa posição retorne undefined. Mas admito que isso não é algo muito comum a se querer fazer.
Peter Olson

88
deletenão atualiza o comprimento da matriz nem apaga o elemento, apenas o substitui pelo valor especial undefined.
Diosney

34
@ Diosney Eu não sei o que você quer dizer quando diz que realmente não apaga o elemento. Além disso, ele faz mais do que simplesmente substituir o valor nesse índice por undefined: remove o índice e o valor da matriz, ou seja delete array[0], depois , "0" in arrayretornará false.
Peter Olson

17
@GrantGryczan Desculpe, eu discordo. Não vejo a necessidade de isso ser removido. O texto acima explica claramente o que faz e ajuda as pessoas que não sabem o que deletefazem a entender por que não funciona como elas esperam.
Peter Olson

1205

Editado em outubro de 2016

  • Faça de forma simples, intuitiva e explícita (a navalha de Occam )
  • Imutável (a matriz original permanece inalterada)
  • Faça isso com funções JavaScript padrão, se o seu navegador não as suportar - use polyfill

Neste exemplo de código, uso a função "array.filter (...)" para remover itens indesejados de uma matriz. Esta função não altera a matriz original e cria uma nova. Se o seu navegador não suportar esta função (por exemplo, Internet Explorer antes da versão 9 ou Firefox antes da versão 1.5), considere usar o polyfill de filtro do Mozilla .

Removendo item (código ECMA-262 Edition 5, também conhecido como JavaScript à moda antiga)

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 ]

Removendo item (código 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 ]

IMPORTANTE A sintaxe da função de seta ECMAScript 6 "() => {}" não é suportada no Internet Explorer, Chrome antes da versão 45, Firefox antes da versão 22 e Safari antes da versão 10. Para usar a sintaxe do ECMAScript 6 em navegadores antigos, você pode usar o BabelJS .


Removendo vários itens (código ECMAScript 7)

Uma vantagem adicional desse método é que você pode remover vários itens

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 ]

A função "array.includes (...)" IMPORTANTE não é suportada no Internet Explorer, Chrome antes da versão 47, Firefox antes da versão 43, Safari antes da versão 9 e Safari antes da versão 9 e Edge antes da versão 14, então aqui está o polyfill do Mozilla .

Removendo vários itens (no futuro, talvez)

Se a proposta "Esta sintaxe de ligação" for aceita, você poderá fazer o seguinte:

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

Tente você mesmo no BabelJS :)

Referência


6
mas, às vezes queremos remover elemento da matriz original (não imutável), por exemplo variedade usada em Angular 2 * ngFor directiva
Ravinder Payal

43
Melhor do que a solução aceita, pois não assume apenas uma ocorrência de uma partida e a imutabilidade é preferível #
Greg

13
filterdeve ser muito mais lento para uma grande variedade embora?
19417 Nathan

3
Qual é o ponto de imutabilidade mencionado se você usou a atribuição da mesma variável em seus exemplos? :)
mench 19/08/19

12
Esta é uma ótima resposta. A emenda é uma função especializada para alterar a não filtragem. filterpode ter um desempenho mais lento, mas é um código mais seguro e melhor. Além disso, você pode filtrar por índice especificando um segundo argumento no lambda:arr.filter((x,i)=>i!==2)
Matthew

449

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

Se você deseja um slot vazio, a exclusão está correta:

delete array[index];

Caso contrário, use o método de emenda :

array.splice(index, 1);

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

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

Caso deseje 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 souber o índice do item, poderá usá array.indexOf(item)-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. 


25
deletenão é a maneira correta de remover um elemento de uma matriz !!
Progo

16
Se você deseja "esvaziar um slot", use array[index] = undefined;. Usar deletedestruirá a otimização.
Bergi

4
@Jakub muito bom comentário porque a entender que eu perdi muito tempo e pensei que meu código de aplicativo é de alguma forma quebrado ...
Pascal

O último parágrafo com a explicação do que você obtém do indexOf foi realmente útil
A. D'Alfonso

277

Um amigo estava com problemas no Internet Explorer 8 e me mostrou o que ele fez. Eu disse a ele que estava errado, e ele me disse que conseguiu a resposta aqui. A resposta superior atual não funcionará em todos os navegadores (Internet Explorer 8, por exemplo) e somente removerá a primeira ocorrência do item.

Remova todas as instâncias de uma matriz

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

Ele percorre a matriz para trás (uma vez que os índices e o comprimento mudam à medida que os itens são removidos) e remove o item, se encontrado. Funciona em todos os navegadores.


11
@sroes não deve ser porque o ciclo começa em i = arr.length -1ou i--tornando-se mesmo que o índice máximo. arr.lengthé apenas um valor inicial para i. i--sempre será verdade (e reduzirá 1 em cada loop op) até que seja igual 0(um valor falso) e o loop será interrompido.
precisa saber é

1
A segunda função é bastante ineficiente. Em toda iteração, "indexOf" iniciará a pesquisa do início da matriz.
ujeenator

3
@AmberdeBlack, em uma coleção com mais de uma ocorrência de item , é muito melhor chamar o método de filtroarr.filter(function (el) { return el !== item }) , evitando a necessidade de alterar a matriz várias vezes. Isso consome um pouco mais de memória, mas opera com muito mais eficiência, pois há menos trabalho que precisa ser feito.
Eugene Kuzmenko

1
@ AlJey, está disponível apenas no IE9 +. Ainda há uma chance de que não funcione.
ujeenator

1
Essa resposta funcionou para mim porque eu precisava de vários itens removidos, mas não em nenhuma ordem específica. A progressão para trás do loop for aqui lida com a remoção perfeita de itens da matriz.
Mintedky

172

Existem duas abordagens principais:

  1. emenda () :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 bom para matrizes. É melhor usar splicepara matrizes.

Lembre-se de que, quando você usa deleteuma matriz, pode obter resultados errados anArray.length. Em outras palavras, deleteremoveria 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 a exclusão, por exemplo, pode acabar tendo os índices 1, 3, 4, 8, 9 e 11 e comprimento como eram antes de usar a exclusão. Nesse caso, todos os forloops indexados travariam, pois os índices não são mais seqüenciais.

Se você for forçado a usar deletepor algum motivo, deverá usar for eachloops quando precisar percorrer matrizes. Na verdade, sempre evite usar forloops indexados , se possível. Dessa forma, o código seria mais robusto e menos propenso a problemas com índices.


144
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)


14
Eu não sou um grande fã dessa abordagem. Se você acabar usando bibliotecas ou estruturas diferentes, elas podem acabar conflitando.
Charlie Kilian


10
Se você está fazendo um for inem uma matriz, você já tem um problema.
Zirak

2
se você fizer for inmatrizes, já terá problemas maiores.
Rainb 01/08/19

use Object.defineProperty stackoverflow.com/a/35518127/3779853 e pronto .
phil294

105

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

Localizar e mover (mover):

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

Uso indexOfe splice(índice):

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 melhorou, removendo a chamada para indexOfa emenda ele executa muito pior do movimento .

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

5
Parece que o método 'mover' apresentado aqui deve funcionar em todos os navegadores e também evita a criação de uma matriz extra; a maioria das outras soluções aqui tem um ou ambos esses problemas. Acho que este merece muito mais votos, mesmo que não pareça "bonito".
Sockmonk

73

Isso fornece um predicado em vez de um valor.

NOTA: ele atualiza a matriz especificada e retorna as linhas afetadas.

Uso

var removed = helper.removeOne(arr, row => row.id === 5 );

var removed = helper.remove(arr, row => row.name.startsWith('BMW'));

Definição

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

Não sei se você precisa da verificação -1 (i> -1). Além disso, acho que essas funções funcionam mais como filtro do que como remover. Se você passar row.id === 5, resultará em uma matriz com apenas o id 5, portanto, estará fazendo o oposto de remove. Ficaria bem no ES2015: var result = ArrayHelper.remove (myArray, linha => row.id === 5);
O que seria legal

@WhatWouldBeCool essa função modifica a matriz original e retorna o item removido em vez de copiar o resultado para uma nova matriz
amd

68

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

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

Isso remove todos os elementos da matriz e também funciona mais rápido que uma combinação de slicee indexOf.


3
Você tem uma fonte sobre isso ser mais rápido?
user3711421

2
Ótima solução. Mas como você aponta, mas importante fazer careca, não produz o mesmo resultado que fatia e indexOf, uma vez que irá remover todas as ocorrências de 1
user3711421

1
@ user3711421 isso ocorre porque apenas fatia e indexOf não fazem o que ele deseja "remover um elemento específico". Ele remove o elemento apenas uma vez, isso remove um elemento específico, não importa quantos deles você tenha #
D Salvador Salvador Dal

66

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 deseja estender um objeto global, pode 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, descobri que ele falha ao tentar remover o penúltimo elemento de uma matriz. Por exemplo, se você tiver uma matriz de 10 elementos e tentar remover o 9º elemento com isso:

myArray.remove(8);

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


Apenas aprendeu pela maneira mais difícil por isso que é uma boa idéia para usar Object.prototype.hasOwnPropertysempre ¬¬
Davi Fiamenghi

64

O Underscore.js pode ser usado para resolver problemas com vários navegadores. Ele usa métodos de navegador embutidos, se presentes. Se estiverem ausentes, como no caso de versões mais antigas do Internet Explorer, ele usa seus próprios métodos personalizados.

Um exemplo simples para remover elementos da matriz (do site):

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

embora elegante e conciso, o OP mencionou claramente apenas o JS principal
EigenFool 16/04

64

Você pode usar o ES6. Por exemplo, para excluir o valor '3' neste caso:

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

Resultado :

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

4
Essa resposta é boa porque cria uma cópia da matriz original, em vez de modificar o original diretamente.
Claudio Holanda

Nota: Array.prototype.filter é ECMAScript 5.1 (No IE8). para soluções mais específicas: stackoverflow.com/a/54390552/8958729
Chang

54

Se você deseja remover uma nova matriz com as posições excluídas, sempre pode excluir o elemento específico e filtrar a matriz. Pode ser necessário uma extensão do objeto de matriz para navegadores que não implementam o método de filtro, mas a longo prazo é mais fácil, pois tudo o que você faz é o seguinte:

var my_array = [1, 2, 3, 4, 5, 6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));

Deve aparecer [1, 2, 3, 4, 6].


45

Confira este código. Funciona em todos os principais navegadores .

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

Chame esta função

remove_item(array,value);

4
@RolandIllig Exceto o uso de um for inloop e o fato de o script poder parar mais cedo, retornando o resultado diretamente do loop. As votações são razoáveis;)
yckart 30/12/14

1
Essa é uma excelente abordagem para matrizes pequenas. Ele funciona em todos os navegadores, usa código mínimo e intuitivo e sem estruturas, shims ou polyfills complexos demais.
Beejor

Também devo reiterar o comentário do yckart que for( i = 0; i < arr.length; i++ )seria uma abordagem melhor, pois preserva os índices exatos versus a ordem em que o navegador decide armazenar os itens (com for in). Isso também permite obter o índice da matriz de um valor, se necessário.
Beejor

41

Você pode usar lodash _.pull (mutate array), _.pullAt (mutate array) ou _.without (não muda o 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']

2
Esse não é o JS principal, conforme solicitado pelo OP, é?
some-non-descript-user

12
@ some-non-descript-user Você está certo. Mas muitos usuários como eu vêm aqui procurando uma resposta geral, não apenas para o OP.
Chun Yang

@ChunYang Você está absolutamente certo. Eu já estou usando o lodash, por que não usá-lo se economizar tempo.
Int # i

38

ES6 e sem mutação: (outubro de 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)


Por que não usar filterentão? array.filter((_, index) => index !== removedIndex);.
user4642212 7/04

@ user4642212 você está certo! também, gostei do sublinhado do estilo Golang
Abdennour TOUMI

36

A remoção de um elemento / string específico de uma matriz pode ser feita em uma única linha:

theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);

Onde:

theArray : a matriz da qual você deseja remover algo específico

stringToRemoveFromArray : a string que você deseja remover e 1 é a quantidade de elementos que você deseja remover.

NOTA : Se "stringToRemoveFromArray" não estiver localizado na sua matriz, isso removerá o último elemento da matriz.

É sempre uma boa prática verificar se o elemento existe em sua matriz primeiro, antes de removê-lo.

if (theArray.indexOf("stringToRemoveFromArray") >= 0){
   theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}

Se você tiver acesso a versões mais recentes do Ecmascript nos computadores do seu cliente (AVISO, pode não funcionar em estações mais antigas):

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

Onde '3' é o valor que você deseja remover da matriz. A matriz se tornaria:['1','2','4','5','6']


Esta é a resposta que funcionou para mim ao tentar atualizar uma matriz com base na alternância de botões de opção.
Jdavid05

4
Cuidado, se "stringToRemoveFromArray"não estiver localizado no seu array, isso removerá o último elemento do array.
Fusion

35

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

Todo o método descrito não altera a matriz original e cria uma nova.

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).concat(items.slice(i+1, items.length))

console.log(filteredItems)

slice()cria uma nova matriz com os índices que recebe. 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 oferecer suporte a 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 assim, escrever o JavaScript moderno em seu código.

Removendo vários itens

E se, em vez de um único item, você desejar 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 alterar a matriz original

splice()(para não confundir slice()) modifica a matriz original e deve ser evitada.

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


34

OK, por exemplo, você tem a matriz abaixo:

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

E queremos excluir o número 4. Você pode simplesmente usar o código abaixo:

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

Se você estiver reutilizando essa função, escreva uma função reutilizável que será anexada à função de matriz nativa como abaixo:

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

Mas e se você tiver a matriz abaixo com alguns [5] s na matriz?

var num = [5, 6, 5, 4, 5, 1, 5];

Precisamos de um loop para verificar todos eles, mas uma maneira mais fácil e eficiente é usar funções JavaScript integradas, por isso escrevemos uma função que usa um filtro como o abaixo:

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]

Além disso, existem bibliotecas de terceiros que ajudam você a fazer isso, como Lodash ou Underscore. Para obter mais informações, consulte lodash _.pull, _.pullAt ou _.without.


Há um pequeno erro de digitação. Por favor corrija. this.splice(num.indexOf(x), 1);=>this.splice(this.indexOf(x), 1);
TheGwa

Por favor, não aumente os recursos internos (anexe funções ao Array.prototype) em JavaScript. Isso é amplamente considerado como uma má prática.
Aikeru24

Concordo que não é a melhor coisa a fazer no mundo, mas, neste caso, como você pode passar para a função?
Alireza

Você deve verificar o índice. Se index = -1, a emenda (-1,1) removerá o último elemento
Richard Chan

29

Eu sou muito novo em JavaScript e precisava dessa funcionalidade. Eu apenas escrevi isso:

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

Então, quando eu quero 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 - conforme o esperado. ["item1", "item1"]

Você pode ter necessidades diferentes das que eu, para poder modificá-las facilmente para atender a elas. Espero que isso ajude alguém.


1
Isso terá um comportamento terrível se sua matriz for realmente longa e houver várias instâncias do elemento. O método indexOf da matriz será iniciado no início de cada vez, portanto, seu custo será O (n ^ 2).
Zag


27

Se você tiver objetos complexos na matriz, poderá usar filtros? Em situações em que $ .inArray ou array.splice não é tão fácil de usar. Especialmente se os objetos forem rasos na matriz.

Por exemplo, se você tem um objeto com um campo Id e deseja que o objeto seja removido de uma matriz:

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

É assim que eu gosto de fazer. Usando uma função de seta, pode ser uma linha. Estou curioso sobre desempenho. Também não vale nada que isso substitua a matriz. Qualquer código com uma referência à matriz antiga não notará a alteração.
Joeytwiddle

27

Quero responder com base no ECMAScript 6 . Suponha que você tenha uma matriz como abaixo:

let arr = [1,2,3,4];

Se você deseja excluir em um índice especial como 2, escreva o código abaixo:

arr.splice(2, 1); //=> arr became [1,2,4]

Mas se você deseja excluir um item especial como 3e não conhece seu índice, faça o seguinte:

arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]

Dica : use uma função de seta para o retorno de chamada do filtro, a menos que você obtenha uma matriz vazia.


25

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


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]

25

atuação

Hoje (09/09/2019) realizo testes de desempenho no macOS v10.13.6 (High Sierra) para as soluções escolhidas. eu mostrodelete (A), mas não o uso em comparação com outros métodos, porque deixou espaço vazio na matriz.

As conclusões

  • a solução mais rápida é array.splice(C) (exceto o Safari para pequenas matrizes em que ocorre pela segunda vez)
  • para grandes matrizes, array.slice+splice(H) é a solução imutável mais rápida para Firefox e Safari; Array.from(B) é o mais rápido no Chrome
  • soluções mutáveis ​​são geralmente 1,5x-6x mais rápidas que imutáveis
  • para pequenas tabelas no Safari, surpreendentemente a solução mutável (C) é mais lenta que a solução imutável (G)

Detalhes

Nos testes, removo o elemento do meio da matriz de maneiras diferentes. As soluções A, C estão em vigor. As soluções B, D, E, F, G, H são imutáveis.

Resultados para array com 10 elementos

Digite a descrição da imagem aqui

No Chrome, o array.splice(C) é a solução local mais rápida. O array.filter(D) é a solução imutável mais rápida. O mais lento é array.slice(F). Você pode executar o teste em sua máquina aqui .

Resultados para array com 1.000.000 elementos

Digite a descrição da imagem aqui

No Chrome, o array.splice(C) é a solução mais rápida no local (o delete(C) é semelhante rapidamente - mas deixou um slot vazio na matriz (para não executar uma 'remoção completa')). O array.slice-splice(H) é a solução imutável mais rápida. O mais lento é array.filter(D e E). Você pode executar o teste em sua máquina aqui .

Comparação para navegadores: Chrome v78.0.0, Safari v13.0.4 e Firefox v71.0.0

Digite a descrição da imagem aqui


24

Você nunca deve alterar sua matriz. Como isso é contra o padrão de programação funcional. Você pode criar uma nova matriz sem fazer referência à matriz da qual deseja alterar os dados usando o método ECMAScript 6 filter;

var myArray = [1, 2, 3, 4, 5, 6];

Suponha que você queira remover 5da matriz, basta fazê-lo da seguinte maneira:

myArray = myArray.filter(value => value !== 5);

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

 [1, 2, 3, 4, 6]; // 5 has been removed from this array

Para um maior entendimento, você pode ler a documentação do MDN em Array.filter .


21

Uma abordagem mais moderna do ECMAScript 2015 (anteriormente conhecida como Harmony ou ES 6). Dado:

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

Então:

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

Produzindo:

[1, 2, 4]

Você pode usar o Babel e um serviço de polyfill para garantir que isso seja bem suportado nos navegadores.


4
Observe que .filterretorna uma nova matriz, que não é exatamente o mesmo que remover o elemento da mesma matriz. O benefício dessa abordagem é que você pode encadear métodos de matriz juntos. por exemplo:[1,2,3].filter(n => n%2).map(n => n*n) === [ 1, 9 ]
CodeOcelot

Ótimo, se eu tiver elementos de 600k na matriz e quiser remover os primeiros 50k, você consegue imaginar essa lentidão? Isso não é solução, há necessidade de função que apenas remove elementos e não retorna nada.
dev1223 30/05

@ Seraph Para isso, você provavelmente gostaria de usar spliceou slice.
Bjfletcher 31/05

@bjfletcher Isso é ainda melhor, no processo de remoção, apenas aloque elementos de 50K e jogue-os em algum lugar. (com fatia de 550K elementos, mas sem jogá-los da janela).
dev1223 31/05

Prefiro a resposta de Bjfletcher, que pode ser tão curta quanto items= items.filter(x=>x!=3). Além disso, o OP não declarou nenhum requisito para um grande conjunto de dados.
runsun

21

Você tem 1 a 9 na matriz e deseja remover 5. Use o código abaixo:

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


Se você deseja vários valores. Exemplo: - 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, 1,7 and 8 removed", newNumberArray);


Se você deseja remover um valor de matriz em uma matriz. Exemplo: [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);

Inclui navegador suportado é link .


19

Sei que já existem muitas respostas, mas muitas parecem complicar demais o problema. Aqui está uma maneira simples e recursiva de remover todas as instâncias de uma chave - chama auto até que o índice não seja encontrado. Sim, ele funciona apenas em navegadores com indexOf, mas é simples e pode ser facilmente preenchido com polyfilled.

Função autônoma

function removeAll(array, key){
    var index = array.indexOf(key);

    if(index === -1) return;

    array.splice(index, 1);
    removeAll(array,key);
}

Método de protótipo

Array.prototype.removeAll = function(key){
    var index = this.indexOf(key);

    if(index === -1) return;

    this.splice(index, 1);
    this.removeAll(key);
}

Apenas uma observação: uma ressalva com esse método é o potencial para estouros de pilha. A menos que você esteja trabalhando com matrizes maciças, não deverá ter um problema.
wharding28

Mas por que um retorno no meio? É efetivamente uma declaração goto.
Peter Mortensen

18

Você pode fazer um loop para trás para garantir que não estrague os índices, se houver várias instâncias do elemento.

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

Demonstração ao vivo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.