Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Group Array of JavaScript Objects by Key or Property Value

Group Array of JavaScript Objects by Key or Property Value

Implementation

const groupBy = key => array =>
  array.reduce((objectsByKeyValue, obj) => {
    const value = obj[key];
    objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
    return objectsByKeyValue;
  }, {});

Or using an implicit return (slower):

const groupBy = key => array =>
  array.reduce(
    (objectsByKeyValue, obj) => ({
      ...objectsByKeyValue,
      [obj[key]]: (objectsByKeyValue[obj[key]] || []).concat(obj)
    }),
    {}
  );

Usage

const cars = [
  { brand: 'Audi', color: 'black' },
  { brand: 'Audi', color: 'white' },
  { brand: 'Ferarri', color: 'red' },
  { brand: 'Ford', color: 'white' },
  { brand: 'Peugot', color: 'white' }
];

const groupByBrand = groupBy('brand');
const groupByColor = groupBy('color');

console.log(
  JSON.stringify({
    carsByBrand: groupByBrand(cars),
    carsByColor: groupByColor(cars)
  }, null, 2)
);

Output

{
  "carsByBrand": {
    "Audi": [
      {
        "brand": "Audi",
        "color": "black"
      },
      {
        "brand": "Audi",
        "color": "white"
      }
    ],
    "Ferarri": [
      {
        "brand": "Ferarri",
        "color": "red"
      }
    ],
    "Ford": [
      {
        "brand": "Ford",
        "color": "white"
      }
    ],
    "Peugot": [
      {
        "brand": "Peugot",
        "color": "white"
      }
    ]
  },
  "carsByColor": {
    "black": [
      {
        "brand": "Audi",
        "color": "black"
      }
    ],
    "white": [
      {
        "brand": "Audi",
        "color": "white"
      },
      {
        "brand": "Ford",
        "color": "white"
      },
      {
        "brand": "Peugot",
        "color": "white"
      }
    ],
    "red": [
      {
        "brand": "Ferarri",
        "color": "red"
      }
    ]
  }
}
@scelloo-elegeonyejerome
Copy link

scelloo-elegeonyejerome commented Feb 2, 2022

@JamieMason Amazing work.. Quick One, how can one get the count of each group?

@JamieMason
Copy link
Author

JamieMason commented Feb 3, 2022

Like this @scelloo-elegeonyejerome:

const groupBy = (key) => (array) =>
  array.reduce((objectsByKeyValue, obj) => {
    const value = obj[key];
    objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
    return objectsByKeyValue;
  }, {});

const cars = [
  { brand: 'Audi', color: 'black' },
  { brand: 'Audi', color: 'white' },
  { brand: 'Ferarri', color: 'red' },
  { brand: 'Ford', color: 'white' },
  { brand: 'Peugot', color: 'white' },
];

const groupByBrand = groupBy('brand');
const carsByBrand = groupByBrand(cars);

Object.entries(carsByBrand).forEach(([brand, cars]) => {
  console.log(`${cars.length} ${brand}`);
});

Outputs

"2 Audi"
"1 Ferarri"
"1 Ford"
"1 Peugot"

@chgad
Copy link

chgad commented Aug 29, 2022

@JamieMason arriving late to the party and newbie to JS: Is there a particular reason for double arrow-functions here or can it be rewritten as function with two parameters key, array ?

@JamieMason
Copy link
Author

JamieMason commented Aug 30, 2022

You could do this @chgad, you're right.

- const groupBy = (key) => (array) =>
+ const groupBy = (key, array) =>

The reason for double arrow-functions (a function creator / a function which returns another function) is so we can do things like this:

export const groupByBrand = groupBy('brand');

so users of your module do this:

groupByBrand(cars);

Instead of this:

groupBy('brand', cars);

Broadly speaking it's a matter of style or taste. It comes from a functional programming-like style of writing JS.

Really – the benefits of it aren't obvious or arguably even applicable in this little example, but generating functions can make for really reusable, readable code. You need to be careful though and develop a sense for knowing when doing this would be an upgrade and not a downgrade.

A rule of thumb would be to not do what I'm doing here, unless you're confident in how to generate and compose functions in a functional style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment