javascript - ta bort objekt från array efter objektets egenskap


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

Hur tar jag bort ett objekt från arrayen genom att matcha objektets egenskap?

Endast native JavaScript, tack.

Jag har problem med att använda splice eftersom längden minskar vid varje borttagning. Att använda clone och splica på originalindexet lämnar dig fortfarande med problemet med minskande längd.

Svar #1

Jag antar att du använde splice på något sätt så här?

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

Allt du behöver göra för att fixa buggen är att minska i inför nästa gång, sedan (och att loopa bakåt är också ett alternativ):

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
        i--;
    }
}

För att undvika borttagningar i linjär tid kan du skriva de array-element du vill behålla över arrayen:

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;

och för att undvika uppslagning i linjär tid i en modern runtime kan du använda en hashmängd:

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;

som kan paketeras i en trevlig funktion:

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

Om du inte behöver göra det på plats, är det Array#filter:

const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));

Svar #2

Du kan ta bort ett objekt genom en av dess egenskaper utan att använda några tredjepartsbibliotek så här:

var removeIndex = array.map(item => item.id).indexOf("abc");

~removeIndex && array.splice(removeIndex, 1);

Svar #3

Med lodash/underscore:

Om du vill ändra den befintliga arrayen själv, då måste vi använda splice. Här är ett lite bättre/läsbar sätt att använda findWhere från underscore/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);

Med ES5 eller högre

(utan lodash/underscore)

Från och med ES5 har vi findIndex-metoden på array, så det är enklare utan lodash/underscore

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

(ES5 stöds i nästan alla moderna webbläsare)

Om findIndex och dess webbläsarkompatibilitet

Svar #4

För att ta bort ett objekt med dess id i en given array;

const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);

Svar #5

findIndex fungerar för moderna webbläsare:

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

Svar #6

Kolla in detta med Set och ES5 filter.

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

Här är JsFiddle: https://jsfiddle.net/jsq0a0p1/1/

Relaterade artiklar