Grouping array items is a common task in programming. You probably wrote a JavaScript grouping function multiple times in your projects. And in the future, you don’t necessarily have to do it again. JavaScript is getting support for array grouping with the static Object.groupBy
and Map.groupBy
methods.
JavaScript Series Overview
- Get the Current URL
- Get URL Query Parameters
- How to Smooth Scroll to an HTML Element
- Sort a Set
- New, Immutable Array Methods
- Detect Network Error
- Create Array from AsyncIterable
- Using the new Array Grouping Methods
Using Object.groupBy
to Group an Array
The new static Object.groupBy
method lets you group arrays by a return value from a callback function. The callback function should return a string or symbol value that’s used as the group key. Other return types than strings or symbols will coerce a string to be usable as the key.
Using the Object.groupBy
function is as simple as this:
const result = Object.groupBy(array, item => item.property)
Let’s look at a specific example and group a dog array by their breed using the Object.groupBy
method:
const dogs = [
{ name: 'Albert', breed: 'Labrador', age: 6 },
{ name: 'Pepper', breed: 'Dachshund', age: 2 },
{ name: 'Rockie', breed: 'German Shepherd', age: 2 },
]
const groupedDogs = Object.groupBy(dogs, dog => dog.breed)
console.log(groupedDogs)
/*
{
Labrador: [
{ name: 'Albert', breed: 'Labrador' }
],
Dachshund: [
{ name: 'Pepper', breed: 'Dachshund' }
],
'German Sheperd': [
{ name: 'Rockie', breed: 'German Shepherd' }
]
}
*/
Notice, that we’re using the breed
property which is a string. If we would use the age
as the group key, JavaScript would cast the number value to a string.
Side note: this is actually the default behavior in JavaScript, numbers as object keys are coerced to a string.
Using Map.groupBy
to Group an Array
The static Map.groupBy
method works like Object.groupBy
. The difference between the two is that Map.groupBy
returns a Map
. This method is helpful when you’re using an object as a group key. JavaScript Map
s support objects as a key and keep reference even if the source object changes.
Use the Map.groupBy
function like this:
const case1 = { name: 'Case 1' }
const case2 = { name: 'Case 2' }
const result = Object.groupBy(array, item => {
return item.property === 'x'
? case1
: case2
})
Let’s use an example of dogs with their owners. We want to group an array of dogs by their owners using the Map.groupBy
method.
const bob = { name: 'Bob' }
const marcus = { name: 'Marcus' }
const dogs = [
{ name: 'Albert', breed: 'Labrador', owner: marcus },
{ name: 'Pepper', breed: 'Dachshund', owner: bob },
{ name: 'Rockie', breed: 'German Shepherd', owner: bob },
]
const map = Map.groupBy(dogs, dog => dog.owner)
console.log(map.get(marcus))
/*
[{ name: 'Albert', breed: 'Labrador', owner: { name: 'Marcus' } }]
*/
Notice: the return value from Map.groupBy
is a Map
instance. It would be best if you retrieve values using the map methods. Also, you must retrieve the values using the owner objects.
The grouping will also work if you’re changing an owner object at runtime. JavaScript keeps the reference and a group result will be accessible by the changed owner object.
Using Array#reduce
to Group an Array
The Object.groupBy
and Map.groupBy
are new additions to the JavaScript language. Both methods are already available in newer versions of Chrome, Edge, Firefox, Safari, mobile versions of the browsers, Node.js, Deno, and Bun.
You should use integrated array methods if you’re developing for the browser and need to support older browser versions. You can use an array’s Array#reduce
method to group it. It’s more manual work compared to Object.groupBy
because you need to write the reducer function yourself:
const dogs = [
{ name: 'Albert', breed: 'Labrador' },
{ name: 'Pepper', breed: 'Dachshund' },
{ name: 'Rockie', breed: 'German Shepherd' },
]
const groupedDogs = dogs.reduce((grouped, dog) => {
const breed = dog.breed
if (!grouped[breed]) {
grouped[breed] = []
}
grouped[breed].push(dog)
return groupedDogs
})
console.log(groupedDogs)
/*
{
Labrador: [
{ name: 'Albert', breed: 'Labrador' }
],
Dachshund: [
{ name: 'Pepper', breed: 'Dachshund' }
],
'German Sheperd': [
{ name: 'Rockie', breed: 'German Shepherd' }
]
}
*/
Supported Browsers and Runtimes
Modern browser versions already support Object.groupBy
and Map.groupBy
. You can use both methods starting from the following browser and runtime versions:
- Chrome 117
- Edge 117
- Firefox 119
- Opera 103
- Safari 17.4
- Node.js 21.0.0
- Deno 1.37
- Bun 1.0.19
Enjoy grouping!