Skip to content Skip to sidebar Skip to footer

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',

Solution 1:

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.


Solution 2:

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);

Solution 3:

I would use Array.prototype.reduce() to create an object with the name part as the key and let the counts accumulate as the values of that object, and then use Object.prototype.entries() to transform this back into an array.

const reducer = (acc, {name}) => {
    acc[name] = acc[name] || 0
    acc[name] += 1
    return acc
}

data.reduce(reducer, {})
    .entries()
    .forEach(([name, count]) => { name, count})

Solution 4:

Another approach to this would be with Array.reduce and Map since Map is kid of made for this really :)

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

const countBy = (arr, prop) => arr.reduce((r,c,i,a) => {
  r.set(c[prop], (r.get(c[prop]) || 0) + 1)  
  return i == a.length-1 ? 
    Array.from(r).map(([k,v]) => ({ name: k, count: v })) : r
}, new Map())

console.log(countBy(data, 'name'))

I made it in a form of a function mimicking what lodash _.countBy (which if you are using you wont get more concise than that) does but with slightly different output:

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

console.log(_.countBy(data, 'name'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Post a Comment for "How To Count Same Object Attribute Values In Array"