Search code examples
javascriptarraysangulartypescriptgroup-by

How to calculate a mean by group in a JS Array?


I work with Angular JS framework and have an array built with NodeJS :

var arr = [{"object":"Anguille","fct":"Type A","value":"2"},{"object":"Athérine","fct":"Type A","value":"1.0031643586595139"}, {"object":"Epinoche","fct":"Type B","value":"1"}, {"object":"Mulet","fct":"Type B","value":"5"}];

I'd like to calculate the mean of "value" grouped by each "fct" so that I could get :

{ 'Type A': 1.5, 'Type B': 3 }

After some researches I managed to group by the values but only with a sum and not a mean. I guess I should use the arr.reduce function but don't really know how to insert it in my code.

Here is my snippet :

const obj = {};
arr.forEach((item) => {
  obj[item.fct] = obj[item.fct] ? obj[item.fct] + 
  parseInt(item.value) : parseInt(item.value);
});

console.log(obj);

I must admit I'm getting stuck. Do you know how to adapt my snippet with a mean instead of a sum ?
Any help would be greatly appreciated, thanks.


Solution

  • You could get the totals and counts from every group and build the mean for the result object.

    const
        data = [{ object: "Anguille", fct: "Type A", value: "2" }, { object: "Athérine", fct: "Type A", value: "1.0031643586595139" }, { object: "Epinoche", fct: "Type B", value: "1" }, { object: "Mulet", fct: "Type B", value: "5" }],
        grouped = data.reduce((r, { fct, value }) => {
            r[fct] ??= { total: 0, count: 0 };
            r[fct].total += +value;
            r[fct].count++;
            return r;
        }, {}),
        result = Object.fromEntries(Object
            .entries(grouped)
            .map(([key, { total, count }]) => [key, total / count])
        );
    
    console.log(result);