eliminar objetos de la matriz por propiedad de objeto

Resuelto Dan Kanze asked hace 11 años • 15 respuestas
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

¿Cómo elimino un objeto de la matriz haciendo coincidir la propiedad del objeto?

Solo JavaScript nativo, por favor.

Tengo problemas para usar el empalme porque la longitud disminuye con cada eliminación. Usar clonación y empalme en el índice original todavía te deja con el problema de disminuir la longitud.

Dan Kanze avatar May 11 '13 05:05 Dan Kanze
Aceptado

¿ Supongo que usaste splicealgo como esto?

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

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

Todo lo que necesita hacer para corregir el error es disminuirlo ipara la próxima vez, luego (y hacer un bucle hacia atrás también es una opción):

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 eliminaciones en tiempo lineal, puede escribir los elementos de la matriz que desea conservar sobre la matriz:

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;

y para evitar búsquedas en tiempo lineal en un tiempo de ejecución moderno, puede utilizar un 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 se puede resumir en una bonita función:

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

Si no necesita hacerlo en el lugar, eso es Array#filter:

const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));
Ry- avatar May 10 '2013 22:05 Ry-

Puede eliminar un elemento mediante una de sus propiedades sin utilizar bibliotecas de terceros como esta:

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

~removeIndex && array.splice(removeIndex, 1);
parliament avatar Oct 12 '2014 16:10 parliament