Map.groupBy()

Groups the elements of an iterable into a Map keyed by whatever the callback returns.

Signature
Map.groupBy(items, callbackFn)
  • Added in JavaScript ES2024

Parameters

ParameterTypeDescription
$itemsIterableAn iterable, such as an Array, whose elements will be grouped.
$callbackFnFunctionA function executed for each element, called with (element, index). Its return value — an object or a primitive — is coerced to the group key using SameValueZero.

Return value

MapA Map with one key per distinct group, each mapped to an array of the elements assigned to that group, in the order the groups were first produced.

Errors

Throws a TypeError when items is not iterable or callbackFn is not callable.

Changelog

  • PHP ES2024Standardized as a static method; Baseline newly available since March 2024.
  • PHP ES2024Replaces the earlier Array.prototype.groupToMap() proposal, which was moved to a static method for web compatibility.

Map.groupBy() replaces the reduce-into-an-object idiom for bucketing a list. It is a static method on Map, not something you call on an array, and it takes any iterable — an array, a Set, another Map's values, a generator.

Why the Map version and not Object.groupBy()

The sibling Object.groupBy() returns a null-prototype plain object and coerces every group key to a string. Reach for Map.groupBy() whenever the grouping key is not a string: an object or class instance you want to look up by reference, a number that must stay a number, true/false, null, or a date bucket. Keys are matched with SameValueZero, so distinct objects returned by the callback form distinct groups — return the same object reference for every member of a group.

Behaviour details

Every element lands in exactly one group; nothing is dropped, and there is no way to skip an element. Group order follows first appearance, and within each group elements keep their original relative order. The values are the original references, not copies. Looking up a group that does not exist returns undefined, not an empty array — use ?? [] when a group may be absent.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Bucket records by a numeric id that must not become a string
  • Group items under an object or class instance used as the category
  • Split a list into true/false partitions in one pass
  • Organize entries by computed date range for a report

Frequently asked questions

What is the difference between Map.groupBy() and Object.groupBy()?

Map.groupBy() returns a Map and keeps the callback's return value as the key unchanged; Object.groupBy() returns a null-prototype object and coerces every key to a string. Use the Map version whenever keys are objects, numbers or booleans.

Why is there no array.groupBy() method?

The proposal was moved to the static methods Map.groupBy() and Object.groupBy() for web compatibility, because adding groupBy to Array.prototype broke existing sites.

Why does Map.groupBy() return undefined for a group I expected?

A group key only exists if at least one element produced it. Requesting an empty group returns undefined rather than an empty array, so write map.get(key) ?? [].

More examples

Numeric keys stay numbers

Map.groupBy() keeps 7 as a number, so get(7) works and get("7") does not. Object.groupBy() stringifies the same keys, which is exactly the loss Map.groupBy() exists to avoid.

Example · javascript
const orders = [
  { id: 1, customer: 7 },
  { id: 2, customer: 12 },
  { id: 3, customer: 7 },
];

const byCustomer = Map.groupBy(orders, (o) => o.customer);
console.log([...byCustomer.keys()]);      // [7, 12]
console.log(typeof [...byCustomer.keys()][0]);
console.log(byCustomer.get(7).length);    // 2
console.log(byCustomer.get("7"));         // undefined

const byObject = Object.groupBy(orders, (o) => o.customer);
console.log(Object.keys(byObject));       // ["7", "12"] — strings

Partitioning and the second callback argument

Boolean keys give a two-way partition without stringifying to "true" and "false". The second grouping uses the index argument, and both show that elements keep their original relative order inside each group.

Example · javascript
const values = [3, 8, 1, 9, 4];

const parts = Map.groupBy(values, (n) => n % 2 === 0);
console.log(parts.get(true));   // [8, 4]
console.log(parts.get(false));  // [3, 1, 9]

const halves = Map.groupBy(values, (n, i) => (i < 2 ? "head" : "tail"));
console.log([...halves]);

Discussion

  • Be the first to comment on this lesson.