Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group javascript mutliarray by indexes and get sum and average

I have a multiarray in Javascript with the following format

[ [string, string, string, number, number], ......]

For example

[
['John', 'Apple', 'Monday', 1, 4.5],
 ['John', 'Orange', 'Monday', 2, 3],
 ['John', 'Apple', 'Monday', 1, 2.5]
]

How can I group the above by the first three items (the strings) and get the sum of the first number and the average of the second number?

The result of above:

[
['John', 'Apple', 'Monday', 2, 3.5],
 ['John', 'Orange', 'Monday', 2, 3],
]

I used to do this with underscore, but now I need to use just Javascript or jQuery.

I found similar questions (not exactly) but didn't help a lot

like image 367
Tasos Avatar asked Jun 28 '26 04:06

Tasos


2 Answers

You could take an object and collect the values for later generating the average.

var array = [['John', 'Apple', 'Monday', 1, 4.5], ['John', 'Orange', 'Monday', 2, 3], ['John', 'Apple', 'Monday', 1, 2.5]],
    result = Object
        .values(array.reduce((r, a) => {
            var key = a.slice(0, 3).join('|');
            if (!r[key]) {
                r[key] = a.slice().concat(1);
                return r;
            }
            r[key][3] += a[3];
            r[key][4] += a[4];
            r[key][5]++;
            return r;
        }, Object.create(null)))
        .map(a => a.slice(0, 4).concat(a[4] / a[5]));

console.log(result);
like image 146
Nina Scholz Avatar answered Jun 30 '26 17:06

Nina Scholz


One option is using .reduce() to group the array. Use .map() and .reduce() to get the total, average and construct the final array.

let arr = [
  ['John', 'Apple', 'Monday', 1, 4.5],
  ['John', 'Orange', 'Monday', 2, 3],
  ['John', 'Apple', 'Monday', 1, 2.5]
];

let result = [...arr.reduce((c, v) => {
  let k = v[0] + v[1] + v[2];
  c.set(k, c.has(k) ? [...c.get(k), v] : [v]);
  return c;
}, new Map()).values()].map(o => {
  let t = o.reduce((c, v) => [c[0] + v[3], c[1] + v[4]], [0, 0]);
  return [o[0][0], o[0][1], o[0][2], t[0], (t[1] / o.length)];
});

console.log(result);
like image 27
Eddie Avatar answered Jun 30 '26 18:06

Eddie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!