Find average value for array of hashes using multiple group by

大城市里の小女人 提交于 2020-01-06 20:18:06

问题


based on Summarize array of objects and calculate average value for each unique object name I could partially solve my problem. I did group by ed_id but I need to group by ed_id and then el_id and to get average value based on those group by, so here is my array of hashes:

a = [
{
 ed_id: 1,
 el_id: 127,
 value: 2
},
{
 ed_id: 1,
 el_id: 127,
 value: 6
},
{
 ed_id: 1,
 el_id: 129,
 value: 3
},
{
 ed_id: 1,
 el_id: 129,
 value: 13
},
{
 ed_id: 2,
 el_id: 127,
 value: 5
},
{
 ed_id: 2,
 el_id: 127,
 value: 9
},
{
 ed_id: 2,
 el_id: 129,
 value: 10
 }
]

So final array of hashes needs to look like:

b = [
{
 ed_id: 1,
 el_id: 127,
 value: 4
},
{
 ed_id: 1,
 el_id: 129,
 value: 8
},
{
 ed_id: 2,
 el_id: 127,
 value: 7
},
{
 ed_id: 2,
 el_id: 129,
 value: 10
 }
]

Thank you!


回答1:


Methods/Functions used:

Array.prototype.reduce(callback[, initialValue]): The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.

Object.prototype.keys(obj): The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).

var data = [
  { ed_id: 1, el_id: 127, value: 2  },
  { ed_id: 1, el_id: 127, value: 6  },
  { ed_id: 1, el_id: 129, value: 3  },
  { ed_id: 1, el_id: 129, value: 13 },
  { ed_id: 2, el_id: 127, value: 5  },
  { ed_id: 2, el_id: 127, value: 9  },
  { ed_id: 2, el_id: 129, value: 10 }
]


// group the data
var groupedData = data.reduce(function(l, r) {
  // construct a unique key out of the properties we want to group by
  var key = r.ed_id + "|" + r.el_id;

  // check if the key is already known
  if (typeof l[key] === "undefined") {
    // init with an "empty" object
    l[key] = {
      sum: 0,
      count: 0
    };
  }
  
  // sum up the values and count the occurences
  l[key].sum += r.value;
  l[key].count += 1;

  return l;
}, {});

console.log(JSON.stringify(groupedData));
//{"1|127":{"sum":8,"count":2},"1|129":{"sum":16,"count":2},"2|127":{"sum":14,"count":2},"2|129":{"sum":10,"count":1}}


// calculate the averages
var avgGroupedData = Object.keys(groupedData)
  // iterate over the elements in <groupedData> and transform them into the "old" format
  .map(function(key) {
    // split the constructed key to get the parts
    var keyParts = key.split(/\|/);

    // construct the "old" format including the average value
    return {
      ed_id: parseInt(keyParts[0], 10),
      el_id: parseInt(keyParts[1], 10),
      value: (groupedData[key].sum / groupedData[key].count)
    };
  });

console.log(JSON.stringify(avgGroupedData));
// [{"ed_id":1,"el_id":127,"value":4},{"ed_id":1,"el_id":129,"value":8},{"ed_id":2,"el_id":127,"value":7},{"ed_id":2,"el_id":129,"value":10}]



回答2:


This should do what you want. Broken down into small functions for readability:

var groupingKey = function(item){
    return item.ed_id + "/" + item.el_id
}

var sum = function(total, item){
    return total + item.value;
}

var average = function(items){
    return _.reduce(items, sum, 0) / items.length;
}

var groupsToResult = function(groups){

    return {
        ed_id: groups[0].ed_id,
        el_id: groups[0].el_id,
        value: average(groups)
    }
}

var result = _.chain(a)
    .groupBy(groupingKey)
    .map(groupsToResult)
    .value();


来源:https://stackoverflow.com/questions/34967609/find-average-value-for-array-of-hashes-using-multiple-group-by

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!