Converting the lodash GroupBy function to plain JavaScript

In this article i’ll walk you through how I converted lodash’s built in groupBy function to plain JavaScript.

TL;DR Here’s the code I came up with to convert the lodash groupBy function

const groupBy = (array, groupByKey) => {
    const uniqueKeys = [...new Set(array.map(item => item[groupByKey]))];
    const groupItems = uniqueKeys.map(key =>
        ({ [key]: array.filter(item => item[groupByKey] === key)}));
};

So i’ve been working on an AngularJS migration at work and there’s a lot of dependency on the lodash library to do things like get nested properties, map and reduce arrays etc.

Which is fine, as lodash is very helpful at doing these kinds of things however there are a lot of these functions that are available natively in JavaScript now (map, reduce, filter etc.) so why not use them?

Plus, we found there was a reasonable performance bottleneck when using some of the functions and converting them to plain JavaScript gave us a much more performant app which is important as a lot of our end users will be on low-spec machines.

What is groupBy?

Anyway, one function which I came across is the lodash groupBy function which (amongst other things) can pick out a common property from an array of objects and return an object with the unique values of the common properties as keys with the values set as the array items that match that particular ‘picked out’ key.

Confused?

Let’s look at an example.

So imagine an array like this:

var cars = [
    {
        make: 'audi',
        model: 'r8',
        year: '2012'
    },
    {
        make: 'audi',
        model: 'rs5',
        year: '2013'
    },
    {
        make: 'ford',
        model: 'mustang',
        year: '2012'
    },
    {
        make: 'ford',
        model: 'fusion',
        year: '2015'
    },
    {
        make: 'kia',
        model: 'optima',
        year: '2012'
    },
];

And we want to convert this to a grouped object like this:

const cars = {
    audi: [
        {
            model: 'r8',
            year: '2012'
        },
        {
            model: 'rs5',
            year: '2013'
        },
    ],
    ford: [
        {
            model: 'mustang',
            year: '2012'
        },
        {
            model: 'fusion',
            year: '2015'
        }
    ],
    kia: [
        {
            model: 'optima',
            year: '2012'
        }
    ]
}

Data courtesy of this SO question: https://stackoverflow.com/questions/40774697/how-to-group-an-array-of-objects-by-key

Pretty handy right?

The trouble is there are several steps to this process so it’s not just as simple as using a single map function for example.

Here’s how I approached it.

Converting lodash groupBy

Breaking down the problem I realised:

  • We need to get a list of unique values for a particular key name
  • We need to return a new object with those values as keys
  • The value of each key in the new object needs to have the items in the original array that match that particular key value

So using the above car data example, step by step that gives us:

Create a new array which has the unique keys.

const groupBy = 'make';
const uniqueKeys = [...new Set(cars.map(car => car[groupBy]))];

Return a new Object

const groupItems = uniqueKeys.map(key => ({ [key]: })); // TBC

Populate the object with the items in the array that match the key

const groupItems = uniqueKeys.map(key =>
    ({ [key]: cars.filter(car => car[groupBy] === key)}));

Obviously you can change the value stored in cars to any array and use a different groupBy value to pick out any particular property from the objects in the array.

Foolproof solution?

There are probably a few issues with this as I don’t know how lodash handles nested arrays for this particular method and we’re obviously relying on the property to exist for each object in the array.

But this seems to do the trick if you want to quickly move away from the lodash groupBy function or you don’t want to have to import the whole library just for this one function.