Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to group an array by a field

Short answer

Object.groupBy() takes a function that returns the group name and builds an object of arrays:

const products = [
  { title: 'Tea', category: 'drinks' },
  { title: 'Bread', category: 'food' },
  { title: 'Coffee', category: 'drinks' },
];
const groups = Object.groupBy(products, (product) => product.category);
 
console.log(groups.drinks.map((p) => p.title).join(', '));
console.log(Object.keys(groups).join(', '));

Output:

Tea, Coffee
drinks, food

With reduce

In older environments, build the same object with reduce():

const products = [
  { title: 'Tea', category: 'drinks' },
  { title: 'Bread', category: 'food' },
  { title: 'Coffee', category: 'drinks' },
];
const groups = products.reduce((result, product) => {
  (result[product.category] ??= []).push(product.title);
  return result;
}, {});
 
console.log(JSON.stringify(groups));

Output:

{"drinks":["Tea","Coffee"],"food":["Bread"]}

By a calculated value

The group can be anything the function returns, for example a range of ages:

const ages = [12, 25, 17, 40, 8];
const groups = Object.groupBy(ages, (age) => (age < 18 ? 'children' : 'adults'));
 
console.log(groups.children.join(', '), '|', groups.adults.join(', '));

Output:

12, 17, 8 | 25, 40

Common mistake

The result of Object.groupBy() has no prototype, so methods like hasOwnProperty() are missing. Use Object.hasOwn() or the in operator:

const groups = Object.groupBy([1, 2, 3], (n) => (n % 2 ? 'odd' : 'even'));
 
console.log(typeof groups.hasOwnProperty);
console.log(Object.hasOwn(groups, 'odd'));

Output:

undefined
true

Functions used in this recipe

Thanks for reading!

Donate to the site — we work hard for you.