Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to count same object attribute values in array

I have a large array with the following structure:

let data = [
  {
    name: 'name1',
    values: {...},
  },
  {
    name: 'name1',
    values: {...},
  },
  {
    name: 'name2',
    values: {...},
  },
  {
    name: 'name1',
    values: {...},
  },
  {
    name: 'name3',
    values: {...},
  },
  ...
]

I need to find a way to count how often each name appears as a name value inside the data array.

So in this example the result should look like the following array:

let nameCounts = [
  {
     name: 'name1'
     count: 3
  },
  {
     name: 'name2'
     count: 1
  },
  {
     name: 'name3'
     count: 1
  }
]

I'm struggling to find good way for this problem. Any ideas?

like image 371
iamrobin. Avatar asked Dec 03 '18 21:12

iamrobin.


2 Answers

You can reduce your array to an object that has names as keys and "count objects" as values. Then you can get your final array with Object.values:

let data = [{
    name: 'name1',
    values: {},
  },
  {
    name: 'name1',
    values: {},
  },
  {
    name: 'name2',
    values: {},
  },
  {
    name: 'name1',
    values: {},
  },
  {
    name: 'name3',
    values: {},
  }
];

var res = Object.values(data.reduce((a, {name}) => {
  a[name] = a[name] || {name, count: 0};
  a[name].count++;
  return a;
}, Object.create(null)));

console.log(res);

Note that I use object destructuring to get the name value from each "current" object in the reduce callback. And the || pattern is standard practice in JS land to assign a default if it's not present.

Also note @ibrahimmahrir's comment about using Object.create(null) to create a prototypeless object for the accumulator.

like image 106
slider Avatar answered Sep 27 '22 20:09

slider


Alternative solution using Array#reduce and Array#map.

const data = [{name:'name1'},{name:'name1'},{name:'name2'},{name:'name1'},{name:'name3'}];

const q = data.reduce((s, { name }) => (s[name] = (s[name] || 0) + 1, s), {});
const r = Object.keys(q).map((key) => ({ name: key, count: q[key] }));

console.log(r);
like image 33
kind user Avatar answered Sep 27 '22 22:09

kind user