yodellingbutters
yodellingbutters

Reputation: 345

In array of objects count grouped values by certain key

I have a following data:

const data2 = [
{
  App: "testa.com",
  Name: "TEST A",
  Category: "HR", 
  Employees: 7
},
{
  App: "testd.com",
  Name: "TEST D",
  Category: "DevOps", 
  Employees: 7
},
{
  App: "teste.com",
  Name: "TEST E",
  Category: "DevOps", 
  Employees: 7
},
{
  App: "testf.com",
  Name: "TEST F",
  Category: "Business", 
  Employees: 7
}
]

I want to get the count of distinct categories: Right now I am getting the list of all distinct categories but I'm unable to compute their count.

Following snippet give me the Distinct Category:

  let uniqueCategory = [];
  for(let i = 0; i < result.data.length; i++){    
      if(uniqueCategory.indexOf(result.data[i].Category) === -1){
        uniqueCategory.push(result.data[i].Category);        
      }        
  }

What changes should I make to get the Counts of those Categories in the uniqueCategory - something like following:

uniqueCategory = [
  {Category: "DevOps", count: 5},
  {Category: "Business", count: 4},
  ....
  {}
]

Upvotes: 2

Views: 537

Answers (3)

Yevhen Horbunkov
Yevhen Horbunkov

Reputation: 15530

Your approach implies looping your source array (with .indexOf()) every iteration of for(..-loop. That will slow down unnecessarily look up process.

Instead, you may employ Array.prototype.reduce() to traverse your source array and build up the Map, having Category as a key and object of desired format as a value, then extract Map.prototype.values() into resulting array.

That will perform much faster and scale better.

const src = [{App:"testa.com",Name:"TEST A",Category:"HR",Employees:7},{App:"testd.com",Name:"TEST D",Category:"DevOps",Employees:7},{App:"teste.com",Name:"TEST E",Category:"DevOps",Employees:7},{App:"testf.com",Name:"TEST F",Category:"Business",Employees:7}],

      result = [...src
        .reduce((r, {Category}) => {
          const cat = r.get(Category)
          cat ? cat.count ++ : r.set(Category, {Category, count: 1})
          return r
        }, new Map)
        .values()
      ]
    
console.log(result)
.as-console-wrapper{min-height:100%;}

Upvotes: 2

Serhii Yukhnevych
Serhii Yukhnevych

Reputation: 299

The easiest way to do it is to use Array.prototype.reduce

const arr = [ ... ];
const output = arr.reduce((result, obj) => {
  if (!result[obj.category]) {
    result[obj.category] = 0;
  }

  result[obj.category]++;

  return result;
}, {});
console.log(output); // this should log the similar output you want

Upvotes: 1

Spencer Bard
Spencer Bard

Reputation: 1035

Here's another alternative using .map and Set:

const src = [
{
  App: "testa.com",
  Name: "TEST A",
  Category: "HR", 
  Employees: 7
},
{
  App: "testd.com",
  Name: "TEST D",
  Category: "DevOps", 
  Employees: 7
},
{
  App: "teste.com",
  Name: "TEST E",
  Category: "DevOps", 
  Employees: 7
},
{
  App: "testf.com",
  Name: "TEST F",
  Category: "Business", 
  Employees: 7
}
];

const categories = src.map(obj => obj.Category);
const distinctCategories = [...new Set(categories)];
console.log(distinctCategories.length);

Upvotes: 0

Related Questions