JavaScript — Using the new Array Grouping Methods

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

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 Maps 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!


Mentioned Resources

Explore the Library

Find interesting tutorials and solutions for your problems.