1
votes

Obtenir des dictionnaires uniques à partir d'un éventail de dictionnaires?

J'ai un tableau qui ressemble à ceci:

  let unique = [...new Set(this.state.dateArray.map(item => item.Group))];
  console.log('UNIQUE: ',unique);

Je voudrais obtenir les valeurs uniques de ce tableau et j'ai essayé de le faire comme ceci:

dateArray = [
      {year:'2018', month: "01"},
      {year:'2018', month: "01"},
      {year:'2017', month: "02"},
      {year:'2017', month: "02"}
    ];

Cette solution ne fonctionne pas. Comment puis-je obtenir les dictionnaires uniques dans un tableau de dictionnaires et les mettre dans un nouveau tableau?


0 commentaires

4 Réponses :


2
votes

Il existe probablement un moyen plus propre, mais cela déduplique votre tableau:

const uniqueDates = [];
dateArray.forEach(date => { // the argument passed to the callback stores the current item
  let unique = true;
  uniqueDates.forEach(uniqueDate => {
    if (uniqueDate.year == date.year && uniqueDate.month == date.month){
      unique = false;    
    }
  });
  if(unique){
    uniqueDates.push(date);
  }
});
console.log(uniqueDates);

Ou la même chose, mais en utilisant .forEach (qui prend une fonction de rappel comme argument, qui peut être un Fonction fléchée ES6 .)

const dateArray = [
  {year:'2018', month: "01"},
  {year:'2018', month: "01"},
  {year:'2017', month: "02"},
  {year:'2017', month: "02"}
];

const uniqueDates = [];
for (let date of dateArray){ // Use "of" to loop through an array
  let unique = true; // Set a flag to handle possible unwanted items 
  for (let uniqueDate of uniqueDates){
    if (uniqueDate.year == date.year && uniqueDate.month == date.month){
      unique = false; // Both properties match, so throw up the flag
    }
  }
  if(unique){ // Only add the item if the flag didn't go up
    uniqueDates.push(date);
  }
}
console.log(uniqueDates);


0 commentaires

2
votes

Vous voulez donc un nouveau tableau avec suppression des doublons? Vous pouvez .filter () le tableau jusqu'aux objets où l'utilisation de .findIndex donne le même index que l'index actuel:

<pre></pre>
dateArray = [
  {year:'2018', month: "01"},
  {year:'2018', month: "01"},
  {year:'2017', month: "02"},
  {year:'2017', month: "02"}
];
    
var unique = dateArray.filter((o, i) =>
  i === dateArray.findIndex(oo => o.year === oo.year && o.month === oo.month)
);

console.log(unique);


0 commentaires

1
votes

Un Set est le type de données approprié pour traiter l'unicité. Malheureusement, dans JS, ceux-ci ne traitent que l'égalité primitive et de référence. Cependant, en transformant nos données vers et à partir de chaînes primitives, nous pouvons en utiliser une pour traiter directement la question de l'unicité.

C'est une version qui le fait:

const uniqDates = ds => [...new Set(ds.map(({year, month}) => `${year}-${month}`))]
  .map(s => s.split('-'))
  .map(([year, month]) => ({year, month}))

const dateArray = [
  {year:'2018', month: "01"},
  {year:'2018', month: "01"},
  {year:'2017', month: "02"},
  {year:'2017', month: "02"}
]

console.log(uniqDates(dateArray))


0 commentaires

1
votes

Quick-n-dirty dans O (n) time:

# WRONG, DO NOT USE!
Array.from(new Set(dateArray.map(JSON.stringify))).map(JSON.parse)

Je ne connais pas de manière générale de traiter facilement les objets comme des valeurs comparables autre que de les stringifier. De plus, JSON.stringify (d) ne convient pas, car l'ordre de sérialisation des champs de l'objet est indéterminé, d'où le conditionnement et le décompression explicites des champs. C'est dommage, car cela aurait pu être beaucoup plus simple:

const dateArray = [
  {year:'2018', month: "01"},
  {year:'2018', month: "01"},
  {year:'2017', month: "02"},
  {year:'2017', month: "02"},
];
console.log(Array.from(new Set(dateArray.map(d => JSON.stringify([d.year, d.month])))).map(
    s => {
        const d = JSON.parse(s);
        return {year: d[0], month: d[1]};
    }
))


0 commentaires