How to Use Lodash countBy to Categorize Data

The _.countBy function in the Lodash JavaScript library is an aggregation utility designed to categorize elements in a collection and return the frequency of each computed category. This article explains the internal mechanics of _.countBy, demonstrates how it uses custom functions and property shorthands to evaluate items, and details the structure of the resulting summary object.

The Mechanics of _.countBy

The _.countBy method iterates over an array or object, executes an iteratee expression for each element, and groups the results. The syntax is:

_.countBy(collection, [iteratee=_.identity])

During execution, the function performs the following steps:

  1. It loops through each item in the provided collection.
  2. It runs the item through the iteratee argument to produce a key.
  3. It uses that key in an accumulator object, setting the initial count to 1 or incrementing the existing count by 1.
  4. It returns an object composed of the generated keys and their corresponding counts.

Categorizing with a Property Name

The simplest way to categorize data is by passing a string representing an object property. The function extracts the value of that property from each item to use as the categorization key.

const users = [
  { name: 'Alice', role: 'admin' },
  { name: 'Bob', role: 'user' },
  { name: 'Charlie', role: 'admin' },
  { name: 'David', role: 'moderator' }
];

const result = _.countBy(users, 'role');
// Output: { admin: 2, user: 1, moderator: 1 }

In this case, _.countBy inspects the role property of each object and increments the count for each unique role found.

Categorizing with a Custom Function

When categorization logic requires transformation or conditional checks, a function can be passed as the iteratee. The return value of the function becomes the key.

const numbers = [4.2, 4.8, 5.1, 5.9, 6.3];

const result = _.countBy(numbers, Math.floor);
// Output: { '4': 2, '5': 2, '6': 1 }

You can also implement custom conditional logic to group items into specific buckets:

const scores = [45, 82, 91, 60, 73, 30];

const resultsByGrade = _.countBy(scores, (score) => {
  return score >= 70 ? 'passed' : 'failed';
});
// Output: { failed: 3, passed: 3 }

Categorization Rules and Edge Cases