remover objects da matriz pela propriedade do object

var listToDelete = ['abc', 'efg']; var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me {id:'efg',name:'em'}, // delete me {id:'hij',name:'ge'}] // all that should remain 

Como faço para remover um object da matriz, combinando a propriedade do object?

Apenas JavaScript nativo por favor.

Estou tendo problemas para usar splice porque o comprimento diminui a cada exclusão. Usando clone e splicing no índice orignal ainda deixa você com o problema de diminuir o comprimento.

Eu suponho que você usou splice algo assim?

 for (var i = 0; i < arrayOfObjects.length; i++) { var obj = arrayOfObjects[i]; if (listToDelete.indexOf(obj.id) !== -1) { arrayOfObjects.splice(i, 1); } } 

Tudo o que você precisa fazer para corrigir o erro é decrementar i para a próxima vez, e (e fazer um loop para trás também é uma opção):

 for (var i = 0; i < arrayOfObjects.length; i++) { var obj = arrayOfObjects[i]; if (listToDelete.indexOf(obj.id) !== -1) { arrayOfObjects.splice(i, 1); i--; } } 

Para evitar exclusões de tempo linear, você pode escrever elementos de matriz que deseja manter sobre o array:

 var end = 0; for (var i = 0; i < arrayOfObjects.length; i++) { var obj = arrayOfObjects[i]; if (listToDelete.indexOf(obj.id) === -1) { arrayOfObjects[end++] = obj; } } arrayOfObjects.length = end; 

e para evitar consultas de tempo linear em um tempo de execução moderno, você pode usar um conjunto de hash:

 const setToDelete = new Set(listToDelete); let end = 0; for (let i = 0; i < arrayOfObjects.length; i++) { const obj = arrayOfObjects[i]; if (setToDelete.has(obj.id)) { arrayOfObjects[end++] = obj; } } arrayOfObjects.length = end; 

que pode ser embrulhado em uma function legal:

 const filterInPlace = (array, predicate) => { let end = 0; for (let i = 0; i < array.length; i++) { const obj = array[i]; if (predicate(obj)) { array[end++] = obj; } } array.length = end; }; const toDelete = new Set(['abc', 'efg']); const arrayOfObjects = [{id: 'abc', name: 'oh'}, {id: 'efg', name: 'em'}, {id: 'hij', name: 'ge'}]; filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id)); console.log(arrayOfObjects); 

Você pode remover um item por uma de suas propriedades sem usar nenhuma biblioteca de terceiros como esta:

 var removeIndex = array.map(function(item) { return item.id; }) .indexOf("abc"); ~removeIndex && array.splice(removeIndex, 1); 

O findIndex funciona para navegadores modernos:

 var myArr = [{id:'a'},{id:'myid'},{id:'c'}]; var index = arr.findIndex(function(o){ return o.id === 'myid'; }) if (index !== -1) myArr.splice(index, 1); 

Com lodash / sublinhado:

Se você quiser modificar o array existente, então precisamos usar splice . Aqui está a maneira pouco melhor / legível usando findWhere de sublinhado / lodash:

 var items= [{id:'abc',name:'oh'}, // delete me {id:'efg',name:'em'}, {id:'hij',name:'ge'}]; items.splice(_.indexOf(items, _.findWhere(items, { id : "abc"})), 1); 

Com ES5 ou superior

( sem lodash / sublinhado )

Com o ES5 em diante, temos o método findIndex no array, então é fácil sem lodash / sublinhado

 items.splice(items.findIndex(function(i){ return i.id === "abc"; }), 1); 

(ES5 é suportado em quase todos os navegadores)

Acerca do findIndex

Se você quiser apenas removê-lo da matriz existente e não criar um novo, tente:

 var items = [{Id: 1},{Id: 2},{Id: 3}]; items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1); 

Faça um loop no reverso decrementando i para evitar o problema:

 for (var i = arrayOfObjects.length - 1; i >= 0; i--) { var obj = arrayOfObjects[i]; if (listToDelete.indexOf(obj.id) !== -1) { arrayOfObjects.splice(i, 1); } } 

Ou use o filter :

 var newArray = arrayOfObjects.filter(function(obj) { return listToDelete.indexOf(obj.id) === -1; }); 

Apenas JavaScript nativo por favor.

Como alternativa, solução mais “funcional”, trabalhando no ECMAScript 5, você poderia usar:

 var listToDelete = ['abc', 'efg']; var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me {id:'efg',name:'em'}, // delete me {id:'hij',name:'ge'}]; // all that should remain arrayOfObjects.reduceRight(function(acc, obj, idx) { if (listToDelete.indexOf(obj.id) > -1) arrayOfObjects.splice(idx,1); }, 0); // initial value set to avoid issues with the first item and // when the array is empty. console.log(arrayOfObjects); [ { id: 'hij', name: 'ge' } ] 

De acordo com a definição de ‘Array.prototype.reduceRight’ no ECMA-262 :

O reduceRight não altera diretamente o object no qual ele é chamado, mas o object pode sofrer mutação pelas chamadas para o callbackfn .

Portanto, este é um uso válido do reduceRight .

 var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me {id:'efg',name:'em'}, // delete me {id:'hij',name:'ge'}] // all that should remain 

como por sua resposta será assim. quando você clica em algum object em particular, envia o índice no parâmetro para a function delete me. Este código simples funcionará como charme.

 function deleteme(i){ if (i > -1) { arrayOfObjects.splice(i, 1); } } 

Se você gosta de parâmetros curtos e auto-descritivos ou se você não quer usar splice e usar um filtro direto ou se você é simplesmente uma pessoa do SQL como eu:

 function removeFromArrayOfHash(p_array_of_hash, p_key, p_value_to_remove){ return p_array_of_hash.filter((l_cur_row) => {return l_cur_row[p_key] != p_value_to_remove}); } 

E um uso de amostra:

 l_test_arr = [ { post_id: 1, post_content: "Hey I am the first hash with id 1" }, { post_id: 2, post_content: "This is item 2" }, { post_id: 1, post_content: "And I am the second hash with id 1" }, { post_id: 3, post_content: "This is item 3" }, ]; l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 2); // gives both of the post_id 1 hashes and the post_id 3 l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 1); // gives only post_id 3 (since 1 was removed in previous line) 

Verifique isso usando o filtro Set e ES6.

  let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) ); console.log(result); 

Aqui está o JsFiddle: https://jsfiddle.net/jsq0a0p1/1/

com filtro e indexOf

 withLodash = _.filter(arrayOfObjects, (obj) => (listToDelete.indexOf(obj.id) === -1)); withoutLodash = arrayOfObjects.filter(obj => listToDelete.indexOf(obj.id) === -1); 

com filtro e inclui

 withLodash = _.filter(arrayOfObjects, (obj) => (!listToDelete.includes(obj.id))) withoutLodash = arrayOfObjects.filter(obj => !listToDelete.includes(obj.id));