2
votes

Comment puis-je supprimer les doublons dans un tableau d'objets?

J'ai un tableau qui ressemble à ceci:

  console.log(this.package.map(pack => pack.values.filter(
    (value, index , array) => array.itemP.indexOf(value) === index
  )))

Je veux supprimer itemP en double donc avec une fonction il ressemblera à ceci:

  console.log(array.map(pack => 
    pack.values.map((item) => {
      var test =  JSON.stringify(item)
      var set = new Set(test)

      return Array.from(set).map((item)=> JSON.parse(item))
      }
    )

  ))


6 commentaires

Pourquoi voudriez-vous rendre l'itemP nul ? Ce n'est pas le plus intelligent à faire, avec angular (de toute façon, partagez votre tentative, je suis presque sûr que vous avez essayé quelque chose)


Oui, il est possible de le faire.


@WashingtonGuedes fera tout mon test que j'ai .filter n'est pas une fonction ou une fin inattendue d'entrée JSON pour le dernier test.


D'accord, vu ce que vous avez essayé, gardez à l'esprit que Set ne fonctionnera pas de cette façon. Les ensembles sont censés être des ensembles de valeurs uniques . Cependant, la stringification d'un élément ne résoudra pas le problème, car les chaînes seront toujours plus ou moins différentes , dans votre exemple. L'approche cartographique peut également être quelque peu évitée car il vous suffit de modifier l'objet existant. Dans tous les cas, puis-je toujours vous demander pourquoi vous voulez rendre cette propriété nulle? Cela n'a pas vraiment de sens pour moi, étant donné que vous utilisez angular. Pouvez-vous encore partager des informations supplémentaires sur l'utilisation?


Utilisez-vous le nom de propriété itemP pour quelque chose? N'est-il pas préférable de n'avoir qu'un seul tableau pour les valeurs? Ce faisant, votre approche de filtrage devrait fonctionner


Oui je dois utiliser itemP Je veux juste l'avoir une fois dans mon code parce que c'est comme si un parent et beaucoup de parents peuvent avoir le même parent mais je ne veux pas montrer 10 fois itemP si j'ai 10 articles qui ont cet itemP en tant que parent. C'est pourquoi j'ai voulu supprimer l'objet et avoir null comme valeur.


4 Réponses :


1
votes

Pour obtenir le résultat attendu, utilisez l'option ci-dessous d'utilisation de la carte

  1. Tableau en boucle à l'aide de la carte
  2. Utilisez nameArr pour vérifier les doublons et attribuer une valeur nulle
  3. Bouclez le tableau de valeurs et vérifiez le nom dans nameArr en utilisant indexOf et attribuez null

var array = [
    {
        key : { id : 1 , pack : "pack 1"},
        values : [
            {
                item : { id : 1 , name : "item1"},
                itemP : {id : 2 , name : "itemP12"}
            },
            {
                item : { id : 4 , name : "item4"},
                itemP : {id : 2 , name : "itemP12"}
            }
        ]
    }
]


console.log(array.map(v => {
  let nameArr = []
  v.values = v.values.map(val => {
    if(nameArr.indexOf(val.itemP.name) !== -1){
      val.itemP.name = null
    }else{
      nameArr.push(val.itemP.name)      
    }
    return val
  })
  return v
}))


0 commentaires

1
votes

Vous pouvez utiliser une carte et un objet pour vérifier s'il existe déjà. Comme

var values = [
            {
                item : { id : 1 , name : "item1"},
                itemP : {id : 2 , name : "itemP12"}
            },
            {
                item : { id : 4 , name : "item4"},
                itemP : {id : 2 , name : "itemP12"}
            }
        ]

values.map((v) => {
    if(!obj[v.itemP.id + '-' + v.itemP.name]) { 
     obj[v.itemP.id + '-' + v.itemP.name] = true; 
     return v;
    }
    return { item : v.item }

})

et boucle sur les valeurs

var obj = {}


0 commentaires

1
votes

Au lieu de mapper chaque propriété de clé, je suggère de cloner toute la structure et de définir la valeur de l'objet comme nulle dans celle clonée, en évitant de muter involontairement la structure d'origine.

function nullifyDupes(array) {
  const clone = JSON.parse(JSON.stringify(array));
  const seen = {};

  clone.forEach(pack => {
    pack.values.forEach(items => {
      for (const item in items) {
        const id = items[item].id;

        if (seen[id]) items[item] = null;
        else seen[id] = true;
      }
    });
  });
  
  return clone;
}

const originalArray = [{
  key : { id : 1 , pack : "pack 1"},
  values : [{
    item : { id : 1 , name : "item1"},
    itemP : {id : 2 , name : "itemP12"}
  },
  {
    item : { id : 4 , name : "item4"},
    itemP : {id : 2 , name : "itemP12"}
  }]
}];

const mutatedArray = nullifyDupes(originalArray);
console.log(mutatedArray);


2 commentaires

Cela fonctionne mais si j'ai plus d'une entrée dans le tableau d'origine, cela ne fonctionne pas, cela supprime également l'élément en double dans une autre clé. const originalArray = [{key: {id: 1, pack: "pack 1"}, values: [{item: {id: 1, name: "item1"}, itemP: {id: 2, name: "itemP12" }}, {item: {id: 4, name: "item4"}, itemP: {id: 2, name: "itemP12"}}]}, {key: {id: 2, pack: "pack 2"} , valeurs: [{item: {id: 1, name: "item1"}, itemP: {id: 2, name: "itemP12"}}, {item: {id: 4, name: "item4"}, itemP : {id: 2, nom: "itemP12"}}]}];


Vous pouvez descendre le const vu = {}; jusqu'à la première ligne de boucle juste après clone.forEach (pack => {. Le vu l'objet serait "effacé" pour chaque pack faisant cela, évitant le cas que vous avez commenté.



1
votes

Vous pouvez mapper vos éléments de tableau à des objets de tableau qui n'incluent pas vos doublons en utilisant .map () . Pour chaque itération de .map () , vous pouvez à nouveau utiliser .map () pour votre tableau de valeurs internes afin de le convertir en un tableau d'objets de telle sorte que les doublons soient convertis en null . Ici, j'ai conservé un objet vu qui garde la trace des propriétés vues et de leurs valeurs stringifiées. En bouclant sur toutes les propriétés de votre objet (en utilisant for ... of ), vous pouvez déterminer si la paire clé-valeur a déjà été vue ou non en utilisant le vu code> objet.

L'avantage de cette approche est qu'elle ne fonctionne pas seulement avec une seule propriété (c'est-à-dire pas seulement itemP ), mais elle fonctionnera avec toute autre paire clé-valeur en double.

Voir l'exemple ci-dessous:

const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];

let itemP = "";
const res = array.map(obj => {
  obj.values = obj.values.map(vobj => {
    vobj.itemP = itemP ? null : vobj.itemP;
    if('itemP' in vobj) {
      itemP = itemP || JSON.stringify(vobj.itemP);
    }
    
    return vobj;
  });
  return obj;
});

console.log(res);

Pour une approche qui vient de supprimer itemP de tous les objets de votre tableau, vous pouvez utiliser:

const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];

const seen = {};
const res = array.map(obj => {
 obj.values = obj.values.map(vobj => {
   for (let p in vobj) {
     vobj[p] = seen[p] === JSON.stringify(vobj[p]) ? null : vobj[p];
     seen[p] = seen[p] || JSON.stringify(vobj[p]);
   }
   return vobj;
 });
 return obj;
});

console.log(res);


7 commentaires

Juste un problème si j'ai un autre objet dans array cela ne fonctionne pas pour l'autre qui a un itemP en double.


@ user10863293 J'ai un peu modifié mon code. Ça marche maintenant?


Cela fonctionne plus mais cela supprime également les éléments qui n'ont pas d'élémentP à la base.


@ user10863293 Ok, je vais réparer ça, donnez-moi quelques minutes


@ user10863293 Ok, j'ai modifié ma réponse (le deuxième extrait de cope devrait être ce que vous recherchez)


^^ 'Maintenant je n'ai pas de null dans un item qui n'a pas d'itemP mais pour l'autre objet dans array il supprime aussi tous les itemP


continuons cette discussion dans le chat .