How to Count the Occurrences of Each Element in an Array in JavaScript
A very common data processing task is to count the frequency of each unique element in an array. This is often called creating a "frequency map" or "histogram." For example, given ['a', 'b', 'a'], you would want to produce an object like { a: 2, b: 1 }.
This guide will teach you the modern and standard methods for solving this problem. You will learn how to use the powerful Array.prototype.reduce() method for a concise solution, and see how to use a Map for a more flexible and often more robust alternative.
Core Method (Most Concise): Array.prototype.reduce()
The reduce() method is the perfect functional tool for transforming an array into a single value, which in this case is our frequency map object. It iterates over the array while building up an accumulator object.
For example, we have an array with duplicate values and we need an object that counts each one.
// Problem: How to count the occurrences of each element?
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
Solution:
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCount = fruits.reduce((accumulator, fruit) => {
accumulator[fruit] = (accumulator[fruit] || 0) + 1;
return accumulator;
}, {});
console.log(fruitCount); // Output: { apple: 3, banana: 2, orange: 1 }
How It Works
reduce((accumulator, fruit) => {...}, {}): We initializereducewith an empty object ({}) as the starting value for ouraccumulator.accumulator[fruit] = ...: On each iteration, we use the current element (fruit) as a key on ouraccumulatorobject.(accumulator[fruit] || 0) + 1: This is a clever one-liner.- It tries to get the current count for the fruit:
accumulator[fruit]. - If the fruit hasn't been seen before, this value will be
undefined. The logical OR (||) operator will then default to0. - We then add
1to this value, either incrementing the existing count or initializing a new one at1.
- It tries to get the current count for the fruit:
An Alternative Method (More Flexible): Using a Map
While using a plain object is very common, a Map is often a more robust choice for a frequency map, especially if your array might contain keys that are not strings (e.g., numbers or even objects).
In the following example, the logic is very similar, but we use the .get() and .set() methods of the Map.
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCount = new Map();
for (const fruit of fruits) {
const currentCount = fruitCount.get(fruit) || 0;
fruitCount.set(fruit, currentCount + 1);
}
console.log(fruitCount);
// Output: Map(3) { 'apple' => 3, 'banana' => 2, 'orange' => 1 }
// You can easily access the count for a specific item
console.log(fruitCount.get('apple')); // Output: 3
This Map-based approach is considered a best practice in modern JavaScript for its flexibility and clear, explicit methods.
The Traditional Method: The for...of Loop
For those who prefer an imperative style, a for...of loop is a perfectly readable and efficient way to build the frequency map object. The logic is identical to the reduce method but is written out step-by-step.
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCount = {};
for (const fruit of fruits) {
if (fruitCount[fruit]) {
// If the fruit is already a key, increment its count
fruitCount[fruit]++;
} else {
// Otherwise, initialize it to 1
fruitCount[fruit] = 1;
}
}
console.log(fruitCount);
// Output: { apple: 3, banana: 2, orange: 1 }
This can also be written with the same concise || trick used in the reduce example:
for (const fruit of fruits) {
fruitCount[fruit] = (fruitCount[fruit] || 0) + 1;
}
Conclusion
Creating a frequency map is a common and useful data transformation. Modern JavaScript offers several clean and effective ways to do it.
- The
reduce()method is the most concise and functional approach for creating a plain object. It is a very common pattern in modern JavaScript codebases. - Using a
Mapwith afor...ofloop is a more robust and flexible solution, especially if your array elements are not strings. This is often considered the modern best practice. - A traditional
for...ofloop with a plain object is also a perfectly valid, readable, and efficient solution.