0
votes

Javascript, filtrage du tableau d'objets et retour de tous les objets uniques

J'ai un tableau d'objets, qui contient des propriétés qui sont des objets:

let result = phones.map(phone => phone.id).filter((value, index, self) => self.indexOf(value) === index)

Ce que je dois faire est de filtrer ces objets et de renvoyer tous les téléphones, en les filtrant par identifiant afin que tous les téléphones retournés soient uniques.

J'ai essayé de récupérer d'abord tous les téléphones:

// allPersons is the full array mentioned above
let phones = [...new Set(allPersons.map(person => person.phone))];

puis j'ai essayé de renvoyer tous les téléphones uniques, mais sans succès:

let allPersons = [
    { id: "abcdefg",
      name: "tom",
      ...
      phone: {
         brand: "blah"
         id: "hijklm"
         ...
     }
   },
   { id: ....}, {...}, {...}
];

Cela ne renvoie que les identifiants uniques des téléphones, mais je veux l'objet entier. Que puis-je faire?

MISE À JOUR: les identifiants de téléphone ne sont PAS uniques, par exemple nokia3310 a l'identifiant 1, nokia3330 a l'identifiant 2, etc.: ainsi tom et john peuvent avoir le même téléphone et les identifiants de téléphone peuvent être dupliqués!


6 commentaires

Voulez-vous dire l' Id de l'objet ou l' Phone Id du Phone Id ?


Les identifiants du téléphone ne sont-ils pas uniques?


@AndresGardiol oui ils sont uniques mais je veux tout l'objet téléphone en retour


@berkobienb le phoneId!


@Diego, si vous voulez que l'objet téléphone entier soit renvoyé, vérifiez ma réponse, il récupère l'objet téléphone entier de chaque objet et les stocke dans un tableau que vous pouvez utiliser


En fait, les identifiants de téléphone sont uniques. Mais les téléphones peuvent être les mêmes chez une personne différente. Donc @RedemptionOkoro dans votre réponse, vous aurez les mêmes téléphones répétés dans le tableau si 2 personnes ou plus ont le même téléphone


3 Réponses :


3
votes

Créez plutôt un objet indexé par ID, puis prenez les valeurs de l'objet:

const phonesById = Object.fromEntries(
  allPersons.map(
    ({ phone }) => [phone.id, phone]
  )
);
const uniquePhones = Object.values(phonesById);


6 commentaires

omg je ne savais même pas que fromEntries existait, je ne savais pas non plus que je pouvais mapper un objet entier {phone} écrit de cette façon! merci beaucoup, je ne pourrais jamais le faire seul


pouvez-vous expliquer la partie de la map ? je ne pense pas avoir compris comment ça marche :)


Vous pouvez consulter la documentation pour plus de clarté: developer.mozilla.org/es/docs/Web/JavaScript/Referencia/... Ce que fait la carte, c'est essentiellement créer un nouveau tableau avec les résultats de l'appel à la fonction indiquée appliquée à chacun de ses éléments. La partie ´ {phone} ´ déstructure l'objet "personne"


@Diego .map transforme un tableau en un autre. Ici, il transforme chaque person en une entrée: une paire clé-valeur pour un nouvel objet, sous la forme d'un tableau à 2 valeurs. Object.fromEntries aura des clés d'entrée ultérieures écrasant les clés précédentes, c'est ainsi que fonctionne la déduplication.


vous voulez dire chaque phone dans une entrée?


J'ai finalement réussi à les écrire dans des fonctions séparées :) Je n'ai jamais vu le bloc ({phone}) => [phone.id, phone] , je pensais que je devais écrire ({phone}) => function { stuff... }



0
votes

Si vous essayez d'obtenir l'objet téléphone dans chaque objet du tableau, le code ci-dessous le fera pour vous.

Il récupère l'objet téléphone et le stocke dans un

var objArr = [
    {id: "abcdefg", name: "tom", phone: {brand: "blah", id: "hijklm"}},
    {id: "guidiuqwbd", name: "john", phone: {brand: "hihihih", id: "ayfva"}},
    {id: "yuygeve", name: "doe", phone: {brand: "hahahah", id: "cqcqw"}}
]

var allPhoneObjects = [];
objArr.forEach(function(currObj){
    var phoneObj = currObj.phone;
    allPhoneObjects.push(phoneObj);
});
console.log(allPhoneObjects);


2 commentaires

Je pense que la question n'est pas claire à ce sujet. Quand il dit "les filtrer par identifiant pour que tous les téléphones retournés soient uniques". Cela me fait penser que les identifiants de téléphone peuvent ne pas être uniques


Si seulement il pouvait apporter une modification à sa question, la rendant plus précise et plus claire



0
votes

Je vous propose la solution suivante

let uniques = new Set();
const phones = allPersons.reduce( (filtered, {phone}) => {
  if (!uniques.has(phone.id)) {
     filtered.push(phone);
     uniques.add(phone.id);
  }
  return filtered
}, [])

Fondamentalement, nous définissons un Set pour enregistrer les ids des téléphones déjà traités, et une fonction de filter sur le tableau allPersons , qui ne renvoie que les téléphones qui ne sont pas déjà dans l'ensemble. Nous complétons avec la map pour extraire uniquement la partie de JSON nécessaire

EDIT Vous ne pouvez utiliser qu'une seule fonction sur le tableau allPersons utilisant la fonction de reduce

let uniques = new Set();
const phones = allPersons.filter(({phone}) => (
  uniques.has(phone.id) ? false : !!uniques.add(phone.id)
)).map(p => p.phone)


2 commentaires

merci, mais avec cette implémentation est retourné l'objet de la personne entière (qui pourrait de toute façon être utile!), mais pour l'instant, je dois renvoyer uniquement l'objet téléphone pour chaque personne, le mettre dans un tableau et être sûr qu'il n'y a pas de téléphones dupliqués ! (regardant leur id)


salut @Diego. Je viens d'exécuter le code une deuxième fois, juste pour m'assurer que je n'ai pas foiré, mais le tableau renvoyé est un tableau de téléphones, et non la personne entière ... Si vous l'exécutez, vous obtiendrez quelque chose comme [{brand: "Nokia", id: "abc123"}, {brand: "Sony", id: "def456"}, {brand: "Apple", id: "ghi789"}]