3
votes

compter le tableau répété de la propriété de l'objet pour produire un nouveau tableau

J'ai ce tableau d'objets

const arr = [{tag: 'james'},{tag: 'james'},{tag: 'john'}];
let newArr = arr.reduce((accum, arr) => {
  accum[arr.tag] = ++accum[arr.tag] || 1
  return accum
}, {})

console.log(newArr)

Comment compter et produire un nouveau tableau comme ci-dessous?

[{
  tag: 'james',
  count: 2
}, {
  tag: 'john',
  count: 1
}]

ma tentative d'utilisation réduire l'objet produit et non le tableau d'objets.

[{
    tag: 'james'
  },
  {
    tag: 'james'
  },
  {
    tag: 'john'
  }
]


0 commentaires

6 Réponses :


0
votes

Commencez par tester si l'objet n'existe pas - si ce n'est pas le cas, créez-en un. Ajoutez ensuite à l'accumulateur. Notez également que vous voulez un tableau, utilisez donc [] et non {} pour la valeur de l'accumulateur:

.as-console-wrapper { max-height: 100% !important; top: auto; }
const data = [{
    tag: 'james'
  },
  {
    tag: 'james'
  },
  {
    tag: 'john'
  }
];

const grouped = data.reduce((acc, { tag }) => {
  if (!acc.some(e => e.tag == tag)) {
    acc.push({ tag, count: 0 });
  }
  acc.find(e => e.tag == tag).count++;
  return acc;
}, []);

console.log(grouped);


0 commentaires

3
votes

Créez un objet au lieu d'un nombre et récupérez enfin ces valeurs de l'objet en utilisant Object.values ​​ méthode.

let arr = [{tag: 'james'},{tag: 'james'},{tag: 'john'}]

let ref = {};

let res = arr.reduce((accum, o) => {
  ref[o.tag] || accum.push(ref[o.tag] = { ...o, count: 0 })
  ref[o.tag].count++;
  return accum
}, []);

console.log(res)

// an object for keeping reference 
let ref = {};

let res = arr.reduce((accum, o) => {
  // check reference already defined, if not define refernece and push to the array
  ref[o.tag] || accum.push(ref[o.tag] = { ...o, count: 0 })
  // update count using the refernece keeped in the object
  ref[o.tag].count++;
  return accum
}, []);


Vous pouvez même créer le tableau directement en utilisant une variable supplémentaire pour le référencement objet / index.

let arr = [{tag: 'james'},{tag: 'james'},{tag: 'john'}]

let res = Object.values(arr.reduce((accum, o) => {
  accum[o.tag] = accum[o.tag] || { ...o, count: 0 }
  accum[o.tag].count++;
  return accum
}, {}))

console.log(res)

// just extract values from the object as an array
let res = Object.values(arr.reduce((accum, o) => {
  // initialize object if not defined already
  accum[o.tag] = accum[o.tag] || { ...o, count: 0  }
  // increment count property
  accum[o.tag].count++;
  return accum
}, {}))


0 commentaires

2
votes

Vous y étiez presque, mais vous devez retirer la clé et la valeur de l'objet et créer un nouveau tableau.

.as-console-wrapper { max-height: 100% !important; top: 0; }
var array = [{ tag: 'jane' }, { tag: 'jane' }, { tag: 'john' }],
    result = Object
        .entries(
            array.reduce((accum, { tag }) => {
                accum[tag] = (accum[tag] || 0) + 1;
                return accum;
            }, {}))
        .map(([tag, count]) => ({ tag, count }));

console.log(result);


2 commentaires

Pourquoi la carte? Celui de Balan semble plus simple let res = Object.values ​​(arr.reduce ((accum, o) => {accum [o.tag] = accum [o.tag] || {... o, count : 0} accum [o.tag] .count ++; return accum}, {}))


ma solution garde la surcharge petite (et abstraite) et construit un objet final, où le code métionné construit directement l'objet final comme valeur de l'objet. cela ressemble à une question de goût.



0
votes

Un code plus simple serait:

const arr = [{
    tag: 'james'
  },
  {
    tag: 'james'
  },
  {
    tag: 'john'
  },
  {
    tag: 'lewis'
  },
  {
    tag: 'john'
  }
]

const counts = arr.reduce((acc, cv) => {
  const val = acc.find(t => t.tag == cv.tag)
  if (val) {
    val.count++
    acc.push(val)
    return acc
  }
  cv.count = 1
  acc.push(cv)
  return acc
}, [])

console.log(counts)


0 commentaires

0
votes

Votre intuition était bonne et vous étiez assez proche; Je vous propose une réponse un peu plus générique

groupTags(data)("tag")

Vous pouvez l'utiliser comme

const groupTags = data => field => Object.values(data.reduce((acc, o) =>
({...acc,
  [o[field]]: {
    [field]: o[field],
    count: acc[o[field]] ? acc[o[field]].count + 1 : 1 
  }
}), {}))


0 commentaires

0
votes
//simple approach using forEach method

let lists = [{tag: 'james'},{tag: 'james'},{tag: 'john'}]; 
const finalOutput = [];
const tempStore = {};

lists.forEach((list) => {
      tempStore[list.tag] = (tempStore[list.tag] == undefined) ? 1: tempStore[list.tag]+1;
      const index = finalOutput.findIndex(e => e.tag == list.tag);
      if(index > -1) {
        finalOutput[index] = {tag: list.tag, count: tempStore[list.tag]}
      }
      else 
        finalOutput.push({tag: list.tag, count: tempStore[list.tag]})
});

console.log(finalOutput);

0 commentaires