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


138
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é d'objet?

Seulement du JavaScript natif s'il vous plaît.

J'ai du mal à utiliser l'épissure car la longueur diminue à chaque suppression. L'utilisation du clone et de l'épissage sur l'index orignal vous laisse toujours le problème de la diminution de la longueur.


1
La boucle en arrière devrait résoudre le problème de changement de longueur
Ian

1
C'est tellement dommage qu'il n'y ait pas de moyen standard approprié de supprimer des éléments d'un tableau d'objets. Pas étonnant qu'il y ait autant de scripts tiers. C'est une chose basique.
guitarlass

Réponses:


155

Je suppose que vous avez utilisé splicequelque chose comme ça?

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 avez à faire pour corriger le bogue est de décrémenter ipour la prochaine fois, puis (et la boucle en arrière est également 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 de temps linéaire, vous pouvez écrire les éléments de tableau que vous souhaitez conserver 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 en temps linéaire dans un environnement d'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 enveloppé dans une belle fonction:

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 en place, c'est Array#filter:

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

79

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

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

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

1
C'est une réponse vraiment élégante.
Scott Silvi

autre chose que je veux, il y aura des boutons séparés pour chaque objet dans le tableau. si je veux supprimer cet objet particulier dans le bouton de tableau cliqué et qui devrait être déplacé vers un autre tableau secondaire. comment faire . J'ai utilisé angular js ng-repeat pour générer des éléments. pouvez-vous m'aider
Thilak Raj

approche très agréable et élégante. gloire! Juste une chose pour la prudence; si l'index requis n'est pas trouvé sur le tableau de la carte, il renverra -1; ainsi l'épissure supprimera le dernier élément.
mcy

15
Ou si vous êtes confus par le tilde sur la dernière ligne, vous pourriez trouver cela plus clair: (removeIndex> = 0) && array.splice (removeIndex, 1);
wojjas

1
@parliament - y a-t-il de la documentation sur le tilde dans votre exemple? Je n'ai jamais vu ça auparavant.
webdad3

43

Avec lodash / soulignement:

Si vous souhaitez modifier le tableau existant lui-même, nous devons utiliser splice . Voici la petite meilleure façon / lisible d'utiliser 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 / soulignement )

Avec ES5, nous avons findIndex méthode sur tableau, donc c'est facile sans lodash / soulignement

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

(ES5 est pris en charge dans presque tous les navigateurs morden)

À propos de findIndex et de sa compatibilité avec le navigateur


comment puis-je supprimer tous les éléments du tableau d'objets mais j'ai également besoin du rappel
Muhaimin

qu'entendez-vous également par rappel, vous pouvez utiliser le code ci-dessus pour supprimer l'objet du tableau ..
Rahul R.

1
Joli. Je vais l'ajouter à ma ceinture à outils
abyrne85

autre chose que je veux, il y aura des boutons séparés pour chaque objet dans le tableau. si je veux supprimer cet objet particulier dans le bouton de tableau cliqué et qui devrait être déplacé vers un autre tableau secondaire. comment faire . J'ai utilisé angular js ng-repeat pour générer des éléments. pouvez-vous m'aider
Thilak Raj

1
J'adore cette suggestion ES5, car elle peut même être écrite de manière plus courteitems.splice(items.findIndex(i => i.id === "abc"), 1)
bramchi

27

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

J'aime cette réponse moderne, sauf que votre code ne
saisit

2
réponse très simple par rapport aux autres et fonctionne très bien.
arun

réponse simple mais puissante
Shelly

15

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

10

Si vous souhaitez simplement le supprimer du tableau existant et ne pas 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);

7
notez que cette réponse nécessite la bibliothèque de soulignements
JoshuaDavid

2
Je ne le recommanderais pas car si l'élément n'est pas trouvé, _.indexOf renverra -1 => items.splice (-1,1)
user1441287

6

Bouclez en sens inverse en décrémentant ipour é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

Seulement du JavaScript natif s'il vous plaît.

Comme solution alternative, plus "fonctionnelle", travaillant sur 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 modifie pas directement l'objet sur lequel il est appelé, mais l'objet peut être muté par les appels à callbackfn .

C'est donc une utilisation valide de reduceRight.


2
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 de la fonction de suppression de moi. Ce code simple fonctionnera comme du charme.

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

1
Thnaks cela a beaucoup aidé :)
RAJESH KUMAR ARUMUGAM

1

avec filtre & indexOf

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

avec filtre et comprend

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

0

Si vous aimez les paramètres courts et auto-descriptifs ou si vous ne voulez pas utiliser spliceet aller avec un filtre simple 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)

-1

Vous pouvez utiliser filter. Cette méthode retourne toujours l'élément si la condition est vraie. Donc, si vous souhaitez supprimer par identifiant, vous devez conserver tous les éléments qui ne correspondent pas à l'identifiant donné. Voici un exemple:

arrayOfObjects = arrayOfObjects.filter (obj => obj.id! = idToRemove)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.