How to count element appearing times

How to count element appearing times?

for example, If I have:

let arr = [2, 3, ,1, 3, 3, 1, 3]

The result is:

let obj = {
  1: 2,
  2: 1,
  3: 4
}

So 1 is appearing two times and number 3 is appearing four times.

A simple loop can do that:

const arr = [2, 3, 1, 3, 3, 1, 3];
let obj = {};
arr.forEach(function (num) {
  const count = obj[num] || 0;
  obj[num] = count + 1;
});

Instead of using count, you can update the obj property first to default to 0, then just increment that.

const arr = [2, 3, 1, 3, 3, 1, 3];
let obj = {};
arr.forEach(function (num) {
  obj[num] = obj[num] || 0;
  obj[num] += 1;
});

Using let though is a signal, warning us that there tends to be better ways to do things.

In this case let is used because we are changing the object. Instead of reaching out to change something (which is typically bad), we can use reduce instead to update an object and return the completed thing.

const arr = [2, 3, 1, 3, 3, 1, 3];
let obj = {};
obj = arr.reduce(function (obj, num) {
  obj[num] = obj[num] || 0;
  obj[num] += 1;
  return obj;
}, {});

That way we can assign that reduced object letting us replace let with const, and are left with better code in the process.

const arr = [2, 3, 1, 3, 3, 1, 3];
const obj = arr.reduce(function (obj, num) {
  obj[num] = obj[num] || 0;
  obj[num] += 1;
  return obj;
}, {});

Can we improve the inside of the function any further?

We could combine both lines that update obj[num]

const arr = [2, 3, 1, 3, 3, 1, 3];
const obj = arr.reduce(function (obj, num) {
  obj[num] = (obj[num] || 0) + 1;
  return obj;
}, {});

Or we could increase the property and only assign a default of 1 for when it starts with no value:

const arr = [2, 3, 1, 3, 3, 1, 3];
const obj = arr.reduce(function (obj, num) {
  obj[num] = (obj[num] + 1) || 1;
  return obj;
}, {});

But I think that I prefer the previous set of code with = (obj[num] || 0) + 1

1 Like