javascript trouver et supprimer un objet dans un tableau en fonction de la valeur de la clé

139

J'ai essayé plusieurs approches pour trouver un objet dans un tableau, où ID = var, et s'il est trouvé, supprimer l'objet du tableau et renvoyer le nouveau tableau d'objets.

Les données:

[
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]

Je suis capable de rechercher le tableau en utilisant jQuery $ grep;

var id = 88;

var result = $.grep(data, function(e){ 
     return e.id == id; 
});

Mais comment puis-je supprimer l'objet entier lorsque id == 88 et renvoyer des données comme ceci:

Les données:

[
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]
À M
la source
Qu'en est-il de l'utilisation de la slicefonction et d'une petite forboucle?
Ahmed Hamdy
1
Bien sûr, mais la raison pour laquelle j'ai écrit cette question, c'est parce que je suis coincé;) des extraits?
Tom
Vérifiez ce message stackoverflow.com/questions/10827894/…
Ahmed Hamdy
Le titre et le texte de la question semblent entrer en conflit ... suggérant deux approches entièrement différentes: A. supprimer des éléments d'un tableau contre B. créer un nouveau tableau filtré.
canon du

Réponses:

155

Je peux grep le tableau pour l'identifiant, mais comment puis-je supprimer l'objet entier où id == 88

Filtrez simplement par le prédicat opposé:

var data = $.grep(data, function(e){ 
     return e.id != id; 
});
Bergi
la source
12
Cette réponse fournit la solution la plus concise et idiomatique pour jQuery
Bryan
1
Dans le cas où vous voulez supprimer tous les éléments avec id = quelque chose est bien ... mais soyez prudent lorsque vous utilisez $ .grep car il recherche le tableau complet et pour les tableaux longs, ce n'est pas efficace. Parfois, vous avez juste besoin de vérifier si l'élément existe à l'intérieur du tableau par un ID donné, alors il est préférable d'utiliser une autre méthode d'itération;)
julianox
1
Cela ne supprime pas cet objet de la liste
Arun Sivan
1
@ArunSivan slicene supprime rien non plus. Je ne sais pas à quoi vous voulez en venir. Si vous avez vous-même un problème spécifique, vous voudrez peut-être poser une nouvelle question .
Bergi
1
@Learnerdata.filter(e => !ids.includes(e.id))
Bergi
153

voici une solution si vous n'utilisez pas jquery:

myArray = myArray.filter(function( obj ) {
  return obj.id !== id;
});
Adam Boostani
la source
2
Est-ce mieux que de faire findIndex()et ensuite splice(index, 1)sur le tableau parent?
Alex
splice mute le tableau d'origine. Avec le filtre, vous avez le choix.
velop
13
Vous pouvez réduire cela à une seule ligne en utilisant: myArr = myArray.filter (obj => obj.id! == id);
DBrown
2
encore plus concisarr = arr.filter( obj => obj.id !== id);
Omar
86

Vous pouvez simplifier cela, et il n'est vraiment pas nécessaire d'utiliser jquery ici.

var id = 88;

for(var i = 0; i < data.length; i++) {
    if(data[i].id == id) {
        data.splice(i, 1);
        break;
    }
}

Parcourez simplement la liste, trouvez l'identifiant correspondant, l'épissure, puis interrompez pour quitter votre boucle

Bryan
la source
17
+1, mais vous devez mentionner que cela ne supprime que le premier élément correspondant.
Bergi
6
... Et si vous devez supprimer chaque élément correspondant, i=data.length; i > 0; i--faites une boucle en ordre inverse avec et ne l'utilisez pas break.
Jeremy Belolo
3
i = data.lengthva casser tout data[i], ça devrait être quelque chose commei=data.length -1 ; i > -1; i--
distante
31

Il existe une nouvelle méthode pour le faire dans ES6 / 2015 en utilisant findIndex et l'opérateur de répartition de tableau:

const index = data.findIndex(obj => obj.id === id);
const newData = [
    ...data.slice(0, index),
    ...data.slice(index + 1)
]

Vous pouvez le transformer en une fonction pour une réutilisation ultérieure comme ceci:

function remove(array, key, value) {
    const index = array.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...array.slice(0, index),
        ...array.slice(index + 1)
    ] : array;
}

De cette façon, vous pouvez supprimer des éléments par différentes clés en utilisant une méthode (et s'il n'y a pas d'objet qui répond aux critères, vous obtenez le tableau d'origine renvoyé):

const newData = remove(data, "id", "88");
const newData2 = remove(data, "name", "You are awesome!");

Ou vous pouvez le mettre sur votre Array.prototype:

Array.prototype.remove = function (key, value) {
    const index = this.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...this.slice(0, index),
        ...this.slice(index + 1)
    ] : this;
};

Et utilisez-le de cette façon:

const newData = data.remove("id", "88");
const newData2 = data.remove("name", "You are awesome!");
Zorza
la source
findIndex () est vraiment génial! 👍
danielcraigie
9

En supposant que les identifiants sont uniques et que vous n'aurez qu'à supprimer un élément, cela splicedevrait faire l'affaire:

var data = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
],
id = 88;

console.table(data);

$.each(data, function(i, el){
  if (this.id == id){
    data.splice(i, 1);
  }
});

console.table(data);
James Hibbard
la source
Vous avez les éléments de votre fonction de rappel à l'envers. Ça devrait être each(data,function(idx,ele). Je vous facturerai plus tard pour les 30 minutes que j'ai
perdues à
Oups. Le moins que je puisse faire dans ce cas est de mettre à jour ma réponse. Je me sens vraiment mal à propos de vos 30 minutes de vie gaspillées.
James Hibbard
5
var items = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

Si vous utilisez jQuery, utilisez jQuery.grep comme ceci:

items = $.grep(items, function(item) { 
  return item.id !== '88';
});
// items => [{ id: "99" }, { id: "108" }]

Utilisation de ES5 Array.prototype.filter :

items = items.filter(function(item) { 
  return item.id !== '88'; 
});
// items => [{ id: "99" }, { id: "108" }]
Nekman
la source
1
Noooooo! N'utilisez pas la jQuerycarte comme filtre.
Bergi
1
Se mettre d'accord! Votre solution avec grep est la bonne solution avec jQuery.
nekman
4

Peut-être recherchez-vous une $.grep()fonction:

arr = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

id = 88;
arr = $.grep(arr, function(data, index) {
   return data.id != id
});
Rafael Garcia
la source
3

siftest un filtre de collecte puissant pour des opérations comme celle-ci et bien plus avancées. Il fonctionne côté client dans le navigateur ou côté serveur dans node.js.

var collection = [
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
];
var sifted = sift({id: {$not: 88}}, collection);

Il prend en charge les filtres tels que $in, $nin, $exists, $gte, $gt, $lte, $lt, $eq, $ne, $mod, $all, $and, $or, $nor, $not, $size, $type, et $regex, et cherche à être compatible avec l' API avec le filtrage de collecte MongoDB.

Redsandro
la source
Pourquoi pas d'upwotes? Si cette chose est correctement écrite et n'a pas de bugs terribles, elle devrait être extrêmement utile.
Max Yari
2
Array.prototype.removeAt = function(id) {
    for (var item in this) {
        if (this[item].id == id) {
            this.splice(item, 1);
            return true;
        }
    }
    return false;
}

Cela devrait faire l'affaire, jsfiddle

casraf
la source
0

Assurez-vous de forcer l'ID de l'objet à un entier si vous testez l'égalité stricte:

var result = $.grep(data, function(e, i) { 
  return +e.id !== id;
});

Démo

Andy
la source
0

Si vous utilisez des traits de soulignement js, il est facile de supprimer un objet en fonction de la clé. http://underscorejs.org . Exemple:

  var temp1=[{id:1,name:"safeer"},  //temp array
             {id:2,name:"jon"},
             {id:3,name:"James"},
             {id:4,name:"deepak"},
             {id:5,name:"ajmal"}];

  var id = _.pluck(temp1,'id'); //get id array from temp1
  var ids=[2,5,10];             //ids to be removed
  var bool_ids=[];
  _.each(ids,function(val){
     bool_ids[val]=true;
  });
  _.filter(temp1,function(val){
     return !bool_ids[val.id];
  });
Mohammed Safeer
la source