Array.Group
and Array.GroupToMap
Editor’s note: This guide to understanding JavaScript’s Array.Group
and Array.GroupToMap
was last updated on 9 January 2023 to reflect changes to the API’s proposal. This update also includes sections comparing the two methods, their benefits, and more information about the most efficient way to group arrays.
The JavaScript specification continues to grow and advance to meet the needs of developers who use the language. ECMAScript (ES) is the standard that defines the different APIs that can be used when coding with JavaScript.
There have been several different ES versions over the years, and each version aims to add more APIs, improve on existing APIs, and ensure that the language remains relevant. The process of adding a new API to the language involves a proposal and multiple approval stages from Stage Zero, where the proposal is planned to be presented to the EMCA committee by a TC39 champion or presented to the committee and not rejected definitively to Stage Four where the proposal will be included in the next ES release.
In June 2021, Justin Ridgewell raised a proposal for adding group
to the Array
API. Grouping data is common but currently unavailable in the standard JavaScript Array
API. Previously, developers had to build their own solutions or use a third-party library.
However, this proposal, which was formerly known as Array.GroupBy
, is currently in Stage Three. This means it’s considered complete, and no further work is possible without implementation experience, significant usage, and external feedback.
This means it should make it into the standard soon. So, let’s take a look at group
and groupToMap
and how we could build our own implementation.
Jump ahead:
group
groupToMap
group
and groupToMap
methodsgroup
group
Moreover, since the group
and groupToMap
array methods are still in the proposal stage, we can’t use them in our JavaScript projects. However, if we use polyfill, browsers will understand what those methods do and run them for us without throwing an error whenever we use them.
Simply put, a polyfill is a code that implements a feature on web browsers that do not natively support the feature. The core-js is a robust polyfill that we can use to make the group
and groupToMap
available in the browser.
To get started with core-js, we can run the following code in our project to install the library:
// Terminal npm install --save [email protected]
Next, we should import it into the file where we want to use the group
and groupToMap
method:
// JavaScript // polyfill all `core-js` features, including early-stage proposals: import "core-js";
For a quick start, you can view an example below:
Array Group Method Example
Array Group Method Example by bonarhyme using core-js, react, react-dom, react-scripts
Before we can start using group
, we need some data to group. When you want to group data, you usually want to take one or more attributes of that data and organize it by that attribute.
For our example, let’s take an array of dogs:
// Javascript const DOGS = [ { name: 'Groucho Barks', breed: 'German Shepherd', age: 1 }, { name: 'Pepper', breed: 'Shih Tzu', age: 3 }, { name: 'Bark Twain', breed: 'Dachshund', age: 5 }, { name: 'Jimmy Chew', breed: 'Shih Tzu', age: 10 }, { name: 'Pup Tar', breed: 'Dachshund', age: 2 }, ]
Our array of dogs is made up of an object for each dog, and each dog has a name
, breed
, and age
. The breed
is the most common attribute, so we will use this to group the data. You can also use age
to get dogs of the same age.
You can also use name
. However, in most cases, the names would not match or group anything. So, let’s see how we can group the data using the proposal:
const byBreed = DOGS.group(dog => { return dog.breed; });
We can use the new group
function by calling it on the array instance, just like a map
, filter
, or reduce
function. group
takes the callback
function called for each element in the array in ascending order.
The group
function returns a new object where each key is the different breeds, and the value is an array of all the matching dogs. If we were to log the byBreed
variable, it would look like the code below:
// Javascript // Value in console { "German Shepherd": [ { "name": "Groucho Barks", "breed": "German Shepherd", "age": 1 } ], "Shih Tzu": [ { "name": "Pepper", "breed": "Shih Tzu", "age": 3 }, { "name": "Jimmy Chew", "breed": "Shih Tzu", "age": 10 } ], "Dachshund": [ { "name": "Bark Twain", "breed": "Dachshund", "age": 5 }, { "name": "Pup Tar", "breed": "Dachshund", "age": 2 } ] }
Here is the group method in been used in a React project:
Array Group Method Example
Array Group Method Example by bonarhyme using core-js, react, react-dom, react-scripts
groupToMap
Like the previous section, you can check out the example below for a quick start:
Array GroupToMap Map Method
Array GroupToMap Map Method by bonarhyme using core-js, react, react-dom, react-scripts
The groupToMap()
method groups the elements in an array using the values returned by its callback
function. It returns a Map
with the unique values from the callback
function as keys, which can be used to access the array of elements in each group. Complex types, such as objects, can be used as keys with the groupToMap()
method.
The method is most useful when grouping elements associated with an object, particularly when that object might change over time. For our example, let’s take an array of athletes:
const ATHLETES = [ { name: 'Blessing Ogabere', nationality: 'Nigerian', age: 26, height: '78ft' }, { name: 'Usain Bolt', nationality: 'Jamican', age: 29, height: '82ft' }, { name: 'Fred KERLEY', nationality: 'USA', age: 16, height: '82ft' }, { name: 'Oblique SEVILLE', nationality: 'Jamican', age: 17, height: '82ft' }, ]
Our array of athletes comprises an object for each athlete
, each with a name
, nationality
, age
, and height
. In order to qualify for an athletic competition, age
is the most common attribute, so we will use this to group the data:
const eligible = {eligible: true }; const ineligible = {ineligible: true }; ATHLETES.groupByToMap((athlete, index, array) => { return athlete.age > 18 ? eligible: ineligible; }); // results: Map { {eligible: true}: [ { name: 'Blessing Ogabere', nationality: 'Nigerian', age: 26, height: '78ft' }, { name: 'Usain Bolt', nationality: 'Jamican', age: 29, height: '82ft' } ], {ineligible: true}: [ { name: 'Fred KERLEY', nationality: 'USA', age: 16, height: '82ft' }, { name: 'Oblique SEVILLE', nationality: 'Jamican', age: 17, height: '82ft' } ] }
The code below uses groupToMap()
with an arrow
function that returns the object keys named eligible
or ineligible
, depending on whether the element has an age greater than 18. The returned result object is a Map
.
In order to obtain an array from a Map
we need to call get()
with the key to obtain the array:
const results = ATHLETES.groupByToMap((athlete) => { return athlete.age > 18 ? eligible: ineligible; }); console.log(results.get(eligible)); //result: [ { name: 'Blessing Ogabere', nationality: 'Nigerian', age: 26, height: '78ft' }, { name: 'Usain Bolt', nationality: 'Jamican', age: 29, height: '82ft' } ]
Here is the groupToMap
method being used in a React project:
Array GroupToMap Map Method
Array GroupToMap Map Method by bonarhyme using core-js, react, react-dom, react-scripts
group
and groupToMap
methodsGroup |
GroupToMap |
This returns a new object where each key is the different keys you sorted with | This returns a Map with the unique values from the callback function as keys, which can be used to access the array of elements in each group |
The results returned can be accessed using the different values that have now been set as keys, just like in a regular object | The results returned can be accessed using the get method available in Maps |
The values of the key specified for the sorting are used to group the array | The custom value you have created is used to group the array |
This does not require a conditional to sort the array | This requires a conditional to group the array |
group
Lodash is the most well-known utility library for JavaScript and was created to tackle many of the missing APIs that did not exist in older versions of JavaScript.
While many APIs now exist, people still use Lodash when building applications. Lodash has a groupBy
function that can be passed as an array and a callback
function. We can see below how we can achieve our dog’s grouping example using Lodash:
import groupBy from 'lodash.groupby'; const byBreed = groupBy(dogs, dog => { return dog.breed; });
This generates the same result as the groupBy
proposal. However, the main difference with using the Lodash version is the need to import the Lodash package and call the function passing in the array instead of calling the function on the array.
Ramda is another JavaScript utility library, and its main difference from Lodash is its functional focus. Ramda is functional programming as a first-class citizen library, and you can easily curry the utility functions.
In the below example, it’s hard to see any difference between it and using Lodash:
import R from 'ramda'; const byBreed = R.groupBy(function(dog) { return dog.breed }); byBreed(DOGS);
In this example, we create a byBreed
function, which we can later call with the list of dogs. We can also pass in the DOGS
when we call Ramda’s groupBy
:
R.groupBy(dog => dog.breed, DOGS);
This archives the same result, but if we use Ramda’s functional nature, we can combine multiple functions:
const byBreed = R.groupBy(function(dog) { return dog.breed }); const reverseName = R.map(function(dog) { return { ...dog, name: dog.name.split('').reverse().join('') } }) const processDogs = R.compose(byBreed, reverseName) processDogs(DOGS);
In this example, we can reverse each dog’s name, group them, and make this a reusable function.
group
Adding an external library like Lodash or Ramda can have benefits and drawbacks. The benefits include the additional utilities that the libraries provide. However, the disadvantages include additional bundle size for the end user and overhead managing third-party dependencies.
Because the group
function is not currently in the core language; you can create your own group
function to use until the official version is released. Let’s look at how we could create our version:
const group = (list, key) => { return list.reduce((prev, curr) => { return { ...prev, [curr[key]]: [ ...(prev[key] || []), curr, ] } }, {}) } group(DOGS, 'breed')
In the above example, we create a new function that takes in a list and a key. This key is what we will group on. We then use the Array.reduce
function to do our grouping.
Our reduce
turns the array of dogs into an object, then iterates over each dog and adds them to the object. It will be created if the breed (key
) does not exist on the object. The value of the object key
is an array where the breed is added.
At the time of writing, the most efficient way to actually group an array is using theArray.reduce
method. This method was used in the example in the create your own group section of this article. However, using the group
and groupToMap
array method means we are actually using a method that has been vetted to work well.
The addition of group
and groupToMap
is a small change to the language. Still, by digging into it, we can see how the JavaScript proposal process works, how existing libraries tackled the challenge, and how we can create our own versions of a function.
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]
2 Replies to "Understanding JavaScript’s <code>Array.Group</code> and <code>Array.GroupToMap</code>"
For the Ramda example you ought to just prop(‘breed’) as in groupBy(prop(‘breed’), DOGS). Otherwise exciting new feature.
Correction for the javascript version:
[curr[key]]: [
…(prev[curr[key]] || []),
curr,
]