web-dev-qa-db-fra.com

supprimer des objets d'un tableau par propriété d'objet

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

Comment supprimer un objet du tableau en faisant correspondre la propriété de l'objet?

Seul JavaScript natif s'il vous plaît.

Je ne parviens pas à utiliser l'épissure car la longueur diminue à chaque suppression . L'utilisation de clones et d'épissures sur l'index d'origine vous laisse toujours le problème de la diminution de la longueur.

104
Dan Kanze

Je suppose que vous avez utilisé splice quelque chose comme ceci?

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

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

Tout ce que vous devez faire pour corriger le bogue est de décrémenter i pour la prochaine fois, puis (et une boucle en arrière est aussi une option):

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

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

Pour éviter les suppressions linéaires, vous pouvez écrire les éléments de tableau que vous voulez garder sur le tableau:

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;

et pour éviter les recherches à temps linéaire dans une exécution moderne, vous pouvez utiliser un ensemble de hachage:

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;

qui peut être intégré à une fonction de Nice:

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

Si vous n’avez pas besoin de le faire sur place, c’est le Array#filter:

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

Vous pouvez supprimer un élément de l'une de ses propriétés sans utiliser de bibliothèque tierce comme celle-ci:

var removeIndex = array.map(function(item) { return item.id; })
                       .indexOf("abc");

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

findIndex fonctionne pour les navigateurs modernes:

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

Avec lodash/underscore:

Si vous voulez modifier le tableau existant lui-même, nous devons utiliser splice. Voici le moyen légèrement meilleur/lisible en utilisant findWhere de 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);

Avec ES5 ou supérieur

(sans lodash/underscore)

À partir de ES5, nous avons la méthode findIndex sur array, ce qui facilite son utilisation sans lodash/underscore 

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

(ES5 est supporté par presque tous les navigateurs morden)

À propos de findIndex

19
Rahul R.

Si vous voulez simplement le supprimer du tableau existant sans en créer un nouveau, essayez:

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

Seulement JavaScript natif s'il vous plaît.

Une solution alternative plus "fonctionnelle", utilisant ECMAScript 5, vous pouvez utiliser:

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' } ]

Selon la définition de 'Array.prototype.reduceRight' dans ECMA-262 :

reductionRight ne mute pas directement l'objet sur lequel il est appelé mais cet objet peut être muté par les appels à callbackfn.

Il s’agit donc d’un usage valide de reduceRight.

5
Sylvain Leroux

Boucle en sens inverse en décrémentant i pour éviter le problème:

for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
    var obj = arrayOfObjects[i];

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

Ou utilisez filter :

var newArray = arrayOfObjects.filter(function(obj) {
    return listToDelete.indexOf(obj.id) === -1;
});
4
Felix Rabe
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

selon votre réponse sera comme ça. Lorsque vous cliquez sur un objet particulier, envoyez l'index dans le paramètre pour la fonction me supprimer. Ce code simple fonctionnera comme un charme.

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

Vérifiez cela en utilisant Set et le filtre ES6.

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

Voici JsFiddle: https://jsfiddle.net/jsq0a0p1/1/

1

Si vous aimez les paramètres courts et auto-descriptifs ou si vous ne voulez pas utiliser splice et optez pour un filtre direct ou si vous êtes simplement une personne SQL comme moi:

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

Et un exemple d'utilisation:

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)
0
Mehmet Kaplan

avec filtre & indexOf

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

avec filtre & comprend

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

Supprimer un objet par son identifiant dans un tableau donné;

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