Search code examples
javascriptgroup-bycount

JavaScript : group by


I have a result variable composed of 3 lists :

var result = {
type: [a,a,b,c,d,a,a,b],
program : [P1, P1, P2, P1, P2, P2, P2, P1],
reference : [ref1,ref2,ref3,...,ref8]}

I want to group my reference by type and program to obtain a dataset like this :

programme type count

P1 a 2

P1 b 1

P1 d 1

P2 a 2

P2 b 1 

P2 d 1

If someone have a solution to do this

Thanks in advance !


Solution

  • You could make a function that gets the data and the list of columnnames to group by. Then keep a running count per group, where a group can be identified by the group keys (serialised from array to JSON):

    function groupByAndCount(data, ...keys) {
        const {length} = keys;
        return Object.values(data[keys[0]].reduce((acc, _, i) => {
            const group = keys.map(key => data[key][i]);
            (acc[JSON.stringify(group)] ??= [...group, 0])[length]++;
            return acc;
        }, {}));
    }
    
    const data = {
      type:      ["a",   "a",   "b",   "c",   "d",   "a",   "a",   "b"   ],
      program:   ["P1",  "P1",  "P2",  "P1",  "P2",  "P2",  "P2",  "P1"  ],
      reference: ["ref1","ref2","ref3","ref4","ref5","ref6","ref7","ref8"]
    }
    
    const result = groupByAndCount(data, "program", "type");
    console.log(result);

    If you want the output to have a similar structure as the input object, then:

    function groupByAndCount(data, ...keys) {
        const {length} = keys;
        const groups = Object.values(data[keys[0]].reduce((acc, _, i) => {
            const group = keys.map(key => data[key][i]);
            (acc[JSON.stringify(group)] ??= [...group, 0])[length]++;
            return acc;
        }, {}));
        return Object.fromEntries(keys.concat("count").map((key, i) =>
            [key, groups.map(group => group[i])]
        ));
    }
    
    const data = {
      type:      ["a",   "a",   "b",   "c",   "d",   "a",   "a",   "b"   ],
      program:   ["P1",  "P1",  "P2",  "P1",  "P2",  "P2",  "P2",  "P1"  ],
      reference: ["ref1","ref2","ref3","ref4","ref5","ref6","ref7","ref8"]
    }
    
    const result = groupByAndCount(data, "program", "type");
    console.log(result);