remove objects from array by object property

前端 未结 13 2973
抹茶落季
抹茶落季 2020-11-22 17:40
var listToDelete = [\'abc\', \'efg\'];

var arrayOfObjects = [{id:\'abc\',name:\'oh\'}, // delete me
                      {id:\'efg\',name:\'em\'}, // delete me
            


        
13条回答
  •  情书的邮戳
    2020-11-22 17:47

    I assume you used splice something like this?

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

    All you need to do to fix the bug is decrement i for the next time around, then (and looping backwards is also an option):

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

    To avoid linear-time deletions, you can write array elements you want to keep over the 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;
    

    and to avoid linear-time lookups in a modern runtime, you can use a hash set:

    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;
    

    which can be wrapped up in a nice function:

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

    If you don’t need to do it in place, that’s Array#filter:

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

提交回复
热议问题