Array.prototype.groupByToMap()
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
The groupByToMap()
method groups the elements of the calling array using the values returned by a provided testing function.
The final returned Map
uses the unique values from the test function as keys, which can be used to get the array of elements in each group.
The method is primarily useful when grouping elements that are associated with an object, and in particular when that object might change over time.
If the object is invariant, you might instead represent it using a string, and group elements with Array.prototype.groupBy()
.
Syntax
// Arrow function
groupByToMap((element) => { /* ... */ } )
groupByToMap((element, index) => { /* ... */ } )
groupByToMap((element, index, array) => { /* ... */ } )
// Callback function
groupByToMap(callbackFn)
groupByToMap(callbackFn, thisArg)
// Inline callback function
groupByToMap(function(element) { /* ... */ })
groupByToMap(function(element, index) { /* ... */ })
groupByToMap(function(element, index, array){ /* ... */ })
groupByToMap(function(element, index, array) { /* ... */ }, thisArg)
Parameters
callbackFn
-
Function to execute on each element in the array.
The function is called with the following arguments:
element
-
The current element in the array.
index
-
The index (position) of the current element in the array.
array
-
The array that
groupByToMap()
was called on.
The value (object or primitive) returned from the callback indicates the group of the current element.
thisArg
Optional-
Object to use as
this
insidecallbackFn
.The argument is ignored in arrow functions, as they have their own lexical scope that will be used instead. Otherwise, if
thisArg
not specified, then either thethis
of the executing scope is used, orundefined
if the function is called in strict mode.
Return value
A Map
object with keys for each group, each assigned to an array containing the elements of the associated group.
Exceptions
TypeError
-
The specified callback function is not callable.
Description
The groupByToMap()
method executes callbackFn
once for each index of the array.
The callback function returns a value indicating the group of the associated element.
The values returned by callbackFn
are used as keys for the Map
returned by groupByToMap()
.
Each key has an associated array containing all the elements for which the callback returned the same value.
The elements in the returned Map
and the original array are the same (not deep copies).
Changing the internal structure of the elements will be reflected in both the original array and the returned Map
.
This method is useful when you need to group information that is related to a particular object that might potentially change over time.
This is because even if the object is modified, it will continue to work as a key to the returned Map
.
If you instead create a string representation for the object and use that as a grouping key in Array.prototype.groupBy()
, you must maintain the mapping between the original object and its representation as the object changes.
Note: To access the groups in the returned Map
, you must use the same object that was originally used as a key in the Map
(although you may modify its properties).
You can't use another object that just happens to have the same name and properties.
callbackFn
is called with the value of the current element, the current index, and the array itself.
While groups often depend only on the current element, it is possible to implement grouping strategies based on the values of other elements in the array.
callbackFn
is invoked for every index of the array, not just those with assigned values.
This means it may be less efficient for sparse arrays, compared to methods that only visit assigned values.
If a thisArg
parameter is provided to groupByToMap()
, it will be used as the this
value inside each invocation of the callbackFn
.
If it is not provided, then undefined
is used.
Mutating the array in the callback
The groupByToMap()
method does not mutate the array on which it is called, but the function provided to callbackFn
can.
Note however that the elements processed by groupByToMap()
are set before the first invocation of callbackFn
.
Therefore:
callbackFn
will not visit any elements added to the array after the call togroupByToMap()
begins.- Elements that are assigned to indexes already visited, or to indexes outside the range, will not be visited by
callbackFn
. - If an existing, yet-unvisited element of the array is changed by
callbackFn
, its value passed to thecallbackFn
will be the value at the timegroupByToMap()
visits that element's index. - Elements that are deleted are still visited.
Warning: Concurrent modifications of the kind described above frequently lead to hard-to-understand code and are generally to be avoided (except in special cases).
Examples
First we define an array containing objects representing an inventory of different foodstuffs.
Each food has a type
and a quantity
.
const inventory = [
{ name: 'asparagus', type: 'vegetables', quantity: 9 },
{ name: 'bananas', type: 'fruit', quantity: 5 },
{ name: 'goat', type: 'meat', quantity: 23 },
{ name: 'cherries', type: 'fruit', quantity: 12 },
{ name: 'fish', type: 'meat', quantity: 22 }
];
The code below uses groupByToMap()
with an arrow function that returns the object keys named restock
or sufficient
, depending on whether the element has quantity < 6
.
The returned result
object is a Map
so we need to call get()
with the key to obtain the array.
const restock = { restock: true };
const sufficient = { restock: false };
const result = inventory.groupByToMap( ({ quantity }) => quantity < 6 ? restock : sufficient );
console.log(result.get(restock));
// expected output: Array [Object { name: "bananas", type: "fruit", quantity: 5 }]
Note that the function argument { quantity }
is a basic example of object destructuring syntax for function arguments.
This unpacks the quantity
property of an object passed as a parameter, and assigns it to a variable named quantity
in the body of the function.
This is a very succinct way to access the relevant values of elements within a function.
The key to a Map
can be modified and still used.
However you can't recreate the key and still use it.
For this reason it is important that anything that needs to use the map keeps a reference to its keys.
// The key can be modified and still used
restock['fast'] = true ;
console.log(result.get(restock));
// expected output: Array [Object { name: "bananas", type: "fruit", quantity: 5 }]
// A new key can't be used, even if it has the same structure!
const restock2 = { restock: true };
console.log(result.get(restock2));
// expected output: undefined
Specifications
Specification |
---|
Array Grouping # sec-array.prototype.groupbymap |
Browser compatibility
BCD tables only load in the browser