ReNinja
ReNinja

Reputation: 573

Groupby and aggregated count by taking an array as the key input in javascript

I have an array of objects lets say data. I want to group this array of objects based on another array lets say arr and also get the accumulated count and get the output for each of the array elements as key. The data variable

const data = [
  {
    "a":"A1",
    "b":"B2",
    "c": "C1",
    "count": 10
  },
  {
    "a":"A1",
    "b":"B1",
    "c": "C2",
    "count": 20
  },
  {
    "a":"A1",
    "b":"B2",
    "c": "C1",
    "count": 50
  },
  {
    "a":"A2",
    "b":"B1",
    "c": "C2",
    "count": 60
  },
  {
    "a":"A2",
    "b":"B2",
    "c": "C2",
    "count": 30
  },
];

The arr variable

const arr = ["a","b","c"];

The result output should be

const result = [
  [
    {
      "key":"a",
      "value":"A1",
      "count": 80
    },
    {
      "key":"a",
      "value":"A2",
      "count": 90
    }
  ],
  [
    {
      "key":"b",
      "value":"B1",
      "count": 80
    },
    {
      "key":"b",
      "value":"B2",
      "count": 90
    }
  ],
  [
    {
      "key":"c",
      "value":"C1",
      "count": 60
    },
    {
      "key":"c",
      "value":"C2",
      "count": 110
    }
  ]
];

I tried the below function but I am not able to group and get accumulated count.

const groupBy = (array, key) => {
  return key.map(keyl => {
  return array.reduce((result, currentValue) => {
      (result[keyl] = result[keyl]|| []).push(
        {"key":keyl,"value": currentValue[keyl],"count":currentValue["count"]}
      );
      
      return result;
    }, {}); 
    })
  
};
const groupByAndCount = groupBy(data, arr);
console.log("groupByAndCount",groupByAndCount)

Upvotes: 0

Views: 70

Answers (2)

deepak
deepak

Reputation: 1375

const data = [{
    a: "A1",
    b: "B2",
    c: "C1",
    count: 10
  },
  {
    a: "A1",
    b: "B1",
    c: "C2",
    count: 20
  },
  {
    a: "A1",
    b: "B2",
    c: "C1",
    count: 50
  },
  {
    a: "A2",
    b: "B1",
    c: "C2",
    count: 60
  },
  {
    a: "A2",
    b: "B2",
    c: "C2",
    count: 30
  }
];

const arr = ["a", "b", "c"];
const groupBy = (array, key) => {
  return key.map((keyl) => {
    return array.reduce((result, item) => {
      const temp = result.filter((it) => it.key === keyl && it.value === item[keyl])[0]
      if (temp) {
        temp["count"] = temp["count"] + item.count;
      } else {
        const obj = {};
        obj.key = keyl;
        obj.value = item[keyl];
        obj.count = item.count;
        result.push(obj);
      }
      return result
    }, []);
  });
};
const groupByAndCount = groupBy(data, arr);
console.log("groupByAndCount", groupByAndCount);

Upvotes: 2

Ele
Ele

Reputation: 33726

You can use this O(n2) approach, which uses the function Array.prototype.reduce for grouping, and the function Object.values for extracting the grouped objects.

const data = [  {    "a":"A1",    "b":"B2",    "c": "C1",    "count": 10  },  {    "a":"A1",    "b":"B1",    "c": "C2",    "count": 20  },  {    "a":"A1",    "b":"B2",    "c": "C1",    "count": 50  },  {    "a":"A2",    "b":"B1",    "c": "C2",    "count": 60  },  {    "a":"A2",    "b":"B2",    "c": "C2",    "count": 30  }],
      arr = ["a","b","c"],
      result = Object.values(Object.values(data.reduce((r, {count, ...c}) => {
        arr.forEach(k => {
          (r[c[k]] || (r[c[k]] = {key: k, value: c[k], count: 0})).count += count;
        });

        return r;
      }, Object.create(null)))
          .reduce((r, {key, ...rest}) => {
            (r[key] || (r[key] = [])).push({key, ...rest});
            return r;
          }, Object.create(null)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions