Loser Coder
Loser Coder

Reputation: 2428

Summarizing data for JSON

{id:1, val:'author', hits:1}, 
{id:1, val:'author', hits:2}, 
{id:1, val:'reviewer', hits:1},
 {id:2, val:'author', hits:100}, 
{id: 1, val:'author', hits:5} 

etc.

I want something that aggregates this data thus (can be Javascript, Jquery, or Angular filters with a single loop)

{id: 1, author:3, reviewer:1, hits:9 }
{id: 2, author:1, reviewer:0, hits:100} 

Breaking my head over this for a bit now!!

Upvotes: 1

Views: 37

Answers (1)

raina77ow
raina77ow

Reputation: 106443

One possible approach:

var source = [
 {id:1, val:'author', hits:1}, 
 {id:1, val:'author', hits:2}, 
 {id:1, val:'reviewer', hits:1},
 {id:2, val:'author', hits:100}, 
 {id: 1, val:'author', hits:5} 
];

var grouped = source.reduce(function(dict, el, i, arr) {
  var obj = dict[el.id];
  if (!obj) {
    obj = {
      id: el.id,
      author: 0,
      reviewer: 0,
      hits: 0
    };
    dict.__arr.push(obj);
    dict[el.id] = obj;
  }
  obj[el.val]++;
  obj.hits += el.hits;
  return i === arr.length - 1? dict.__arr : dict;
}, {__arr:[]});

Demo. As often, when you need to group items by some criteria, you use Array.reduce with some dictionary object to organize the grouping process. In this case, it's just a bit more complicated because you need to get the resulting array from the single loop; the dictionary object is supplied with a specific property ('__arr') that's filled while dictionary is constructed. In the end (checked with i === arr.length - 1) this array is given out as a result of .reduce.

Upvotes: 1

Related Questions