Remover elemento da matriz com base na propriedade do objeto

271

Eu tenho uma matriz de objetos como este:

var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];

Como removo um específico com base em sua propriedade?

Por exemplo, como removeria o objeto de matriz com 'money' como a propriedade do campo?

imperium2335
fonte

Respostas:

384

Uma possibilidade:

myArray = myArray.filter(function( obj ) {
    return obj.field !== 'money';
});

Observe que filtercria uma nova matriz. Quaisquer outras variáveis ​​referentes à matriz original não receberão os dados filtrados, embora você atualize sua variável original myArraycom a nova referência. Use com cuidado.

jAndy
fonte
6
Observe que filter()está disponível apenas para o Internet Explorer 9+
jessegavin
@jessegavin de fato. Eu deveria ter mencionado que há uma abundância de boa ES5 calço bibliotecas disponíveis, que imitam a funcionalidade (apenas no caso de você querer navegadores suporte legado)
Jandy
3
filter()cria uma nova matriz, o que é bom se você puder reatribuir a variável e saber que não há outras áreas do código que tenham referências a ela. Isso não funcionará se você precisar modificar especificamente o objeto original da matriz.
Brian Glick 26/09
2
E se a matriz for uma estrutura em árvore antes deDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "alterou o teste 23"}]}] e eu quero excluir id: 23
forgottofly
@forgottofly good point - a resposta funciona apenas em casos limitados. Você encontrou a resposta para sua pergunta?
21419 JackTheKnife
88

Iterar através da matriz, e splicefora os que você não deseja. Para um uso mais fácil, itere para trás para que você não precise levar em consideração a natureza ativa da matriz:

for (var i = myArray.length - 1; i >= 0; --i) {
    if (myArray[i].field == "money") {
        myArray.splice(i,1);
    }
}
Niet, o Escuro Absol
fonte
3
o que você quer dizer com a natureza viva da matriz? @Neit the Dark Absol
sisimh
29
@sisimh ele significa que, se você iterar para a frente em uma matriz usando seu comprimento como parte da lógica de iteração e seu comprimento for alterado porque possui elementos removidos ou adicionados, você pode acabar fugindo do final da matriz ou não fazendo a operação para todos os itens da matriz. Retroceder torna muito menos provável, pois trabalha em direção a um índice 0 estático, em vez de um comprimento móvel.
Klors
2
E se a matriz for uma estrutura em árvore antes deDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "alterou o teste 23"}]}] e eu quero excluir id: 23
forgottofly
Meio óbvio, mas se você está apenas esperando remover um único elemento único, pode interromper a instrução 'if' para obter desempenho, para que o loop não interaja desnecessariamente com o restante da matriz.
Patrick Borkowicz 31/03
@ Klors Obrigado por explicar. É bom sempre ler a matriz ao contrário, como na resposta?
Kittu
38

Digamos que você queira remover o segundo objeto por sua propriedade de campo.

Com o ES6, é tão fácil quanto isso.

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)
Peracek
fonte
7
Eu tentei isso, mas em vez de "remover" o terceiro item da matriz do OP, seu código "filtrou" e exibiu apenas o terceiro item.
Compaq LE2202x 30/07/2018
1
@ CompaqLE2202x 2 anos depois, provavelmente já é óbvio para você, mas para futuros desenvolvedores: splicealtera a matriz original, então o valor que você recebe é o item que foi removido, mas se você olhar novamente o item em myArrayfalta.
David Mulder
17

Você pode usar o findIndex do lodash para obter o índice do elemento específico e depois emendá-lo.

myArray.splice(_.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

Atualizar

Você também pode usar o findIndex () do ES6

O método findIndex () retorna o índice do primeiro elemento na matriz que satisfaz a função de teste fornecida. Caso contrário, -1 será retornado.

myArray.splice(myArray.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);
Sridhar
fonte
Qual é a matriz é uma estrutura de árvore?
precisa saber é o seguinte
@forgottofly estrutura da árvore? Eu acho que myArrayaqui está uma variedade de objetos.
Sridhar
4
E se a matriz for uma estrutura em árvore var beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "alterou o teste 23"}]}] e quero excluir o id: 23
forgottofly
9

Aqui está outra opção usando o jQuery grep. Passe truecomo o terceiro parâmetro para garantir que o grep remova itens que correspondam à sua função.

users = $.grep(users, function(el, idx) {return el.field == "money"}, true)

Se você já está usando jQuery, não é necessário usar shim, o que pode ser útil em vez de usar Array.filter.

sexta-feira
fonte
8

No ES6, apenas uma linha.

const arr = arr.filter(item => item.key !== "some value");

:)

Supun Kavinda
fonte
3

A seguir está o código se você não estiver usando o jQuery. Demo

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];

alert(myArray.length);

for(var i=0 ; i<myArray.length; i++)
{
    if(myArray[i].value=='money')
        myArray.splice(i);
}

alert(myArray.length);

Você também pode usar a biblioteca de sublinhado, que possui muitas funções.

O Underscore é uma biblioteca de cinto de utilidade para JavaScript que fornece grande parte do suporte à programação funcional

Umair Saleem
fonte
5
Este é um exemplo muito perigoso para deixar na web ... ele funciona com os dados de exemplo, mas não com mais nada. splice (i) significa que ele removerá todos os elementos da matriz, iniciando na e após a primeira instância em que o valor é dinheiro, que não satisfaz a exigência de op. Se mudássemos para emenda (i, 1), ainda estaria incorreto porque não avaliaria o próximo item seqüencial (você também precisaria decrementar i). É por isso que você deve processar operações de remoção de matrizes para trás, para remover uma item não altera os índices dos próximos itens a serem processados
Chris Schaller
3
var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];
console.log(myArray.length); //3
myArray = $.grep(myArray, function(element, index){return element.field == "money"}, true);
console.log(myArray.length); //2

Elemento é um objeto na matriz. O terceiro parâmetro truesignifica que retornará uma matriz de elementos que falharão na lógica de sua função, falsesignifica que retornará uma matriz de elementos que falharão na sua lógica de função.

Sandeep sandy
fonte
3

Com base em alguns comentários acima abaixo, está o código de como remover um objeto com base no nome e no valor da chave

 var items = [ 
  { "id": 3.1, "name": "test 3.1"}, 
  { "id": 22, "name": "test 3.1" }, 
  { "id": 23, "name": "changed test 23" } 
  ]

    function removeByKey(array, params){
      array.some(function(item, index) {
        return (array[index][params.key] === params.value) ? !!(array.splice(index, 1)) : false;
      });
      return array;
    }

    var removed = removeByKey(items, {
      key: 'id',
      value: 23
    });

    console.log(removed);
JackTheKnife
fonte
3

Usando a biblioteca lodash :

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];
var newArray = _.remove(myArray, function(n) {
  return n.value === 'money';;
});
console.log('Array');
console.log(myArray);
console.log('New Array');
console.log(newArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

Parth Raval
fonte
1

A solução de jAndy é provavelmente a melhor, mas se você não puder confiar no filtro, poderá fazer algo como:

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: "money"}
];

myArray.remove_key = function(key){
    var i = 0, 
        keyval = null;
    for( ; i < this.length; i++){
        if(this[i].field == key){
            keyval = this.splice(i, 1);
            break;
        }
    }
    return keyval;
}
Rob M.
fonte
1
Por que eu não poderia confiar no filter ()?
imperium2335
2
Porque faz parte do JavaScript 1.6, que não é suportado pelo IE8 e navegadores abaixo ou mais antigos.
Rob M.
-1

Usando a biblioteca lodash, é simples, pois

_.remove(myArray , { field: 'money' });
Gimnath
fonte