-2

I'm trying to make a simple "top 3" of the users that have the most messages. So far I was able to group the user and messages inside an array of objects

let data = [ { message: 'fsaasfafs', user: 'John' },
  { message: 'asgsgaasgags', user: 'John' },
  { message: 'asgsgaasgags', user: 'John' },
  { message: 'asgsgaasgags', user: 'Smith' },
  { message: 'asgsgaasgags', user: 'Samantha' },
  { message: 'asgsgaasgags', user: 'Luis' },
  { message: 'asgsgaasgags', user: 'Samantha' }]

console.log(data);

In this case, the top 3 would be John - 3 ; Samantha - 2; Smith or Luis (does not matter) - 1 I would like a map with the user as key and the amount of messages.

Any help please?

Tiago
  • 69
  • 1
  • 7
  • Please post what you have tried to achieve the desired result. – Krishna Prashatt Nov 07 '19 at 11:01
  • @jonas - How does [*sorting*](https://stackoverflow.com/questions/979256/sorting-an-array-of-javascript-objects-by-property) answer this question? (I've added a dupe that I think does, I'm just curious about the one you picked.) – T.J. Crowder Nov 07 '19 at 11:02
  • @t.j. well, I was just about to do the same (adding a few more duplicates), but you two were faster :) – Jonas Wilms Nov 07 '19 at 11:03
  • `let statsMap = {}; data.forEach(message => { if(statsMap.hasProperty(message.user)) { } else { statsMap[message.user] = } });` i got stuck – Tiago Nov 07 '19 at 11:05

2 Answers2

1

    let data = [ { message: 'fsaasfafs', user: 'John' },
      { message: 'asgsgaasgags', user: 'John' },
      { message: 'asgsgaasgags', user: 'John' },
      { message: 'asgsgaasgags', user: 'Smith' },
      { message: 'asgsgaasgags', user: 'Samantha' },
      { message: 'asgsgaasgags', user: 'Luis' },
      { message: 'asgsgaasgags', user: 'Samantha' }];
      
    let topM = Object.entries(data.reduce((acc, c) => { acc[c.user] = (acc[c.user] || 0 ) + 1; return acc;},{})).sort(function (a, b) { return b[1] - a[1];}).slice(0, 3);
    console.log(topM);

Hope This helps you !

Saurabh Yadav
  • 3,303
  • 1
  • 10
  • 20
0

You could do like get count of each user message

  1. Then you could count the each user messages using Array#reduce with Array#filter(this will match the user count in array for each user)

let data = [ { message: 'fsaasfafs', user: 'John' },
  { message: 'asgsgaasgags', user: 'John' },
  { message: 'asgsgaasgags', user: 'John' },
  { message: 'asgsgaasgags', user: 'Smith' },
  { message: 'asgsgaasgags', user: 'Samantha' },
  { message: 'asgsgaasgags', user: 'Luis' },
  { message: 'asgsgaasgags', user: 'Samantha' }]
  
 let user_list = data.reduce((a,b,c,d)=>{
   if(Object.keys(a).indexOf(b.user) == -1){
    a[b.user] = d.filter(i=>i.user == b.user).length
   }
   return a
 },{})
 
 console.log(user_list)
prasanth
  • 22,145
  • 4
  • 29
  • 53
  • please explain :/ – Tiago Nov 07 '19 at 11:07
  • 1
    This is not very efficient. Not only does it involve three iterations (`map`, `filter`, and `reduce`) when it could be done in one, it also has a nested iteration happening with `indexOf`, which gives it a *O(n²)* time complexity. On top of that, this question has been asked before and has useful answers already. – trincot Nov 07 '19 at 11:15
  • @trincot i just update method with single parent loop – prasanth Nov 07 '19 at 11:24