Last active
February 25, 2025 20:51
-
-
Save gtrabanco/7c97bd41aa74af974fa935bfb5044b6e to your computer and use it in GitHub Desktop.
Object.groupBy polyfill
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const hasGroup = typeof Object.groupBy === typeof undefined || typeof Array.groupToMap === typeof undefined || typeof Array.group === typeof undefined; | |
if (!hasGroup) { | |
const groupBy = (arr, callback) => { | |
return arr.reduce((acc = {}, ...args) => { | |
const key = callback(...args); | |
acc[key] ??= [] | |
acc[key].push(args[0]); | |
return acc; | |
}, {}); | |
}; | |
if (typeof Object.groupBy === typeof undefined) { | |
Object.groupBy = groupBy; | |
} | |
if (typeof Array.groupToMap === typeof undefined) { | |
Array.groupToMap = groupBy; | |
} | |
if (typeof Array.group === typeof undefined) { | |
Array.group = groupBy; | |
} | |
} | |
// There are better approaches using loops directly instead of reduce | |
// Example: | |
console.log( | |
Object.groupBy( | |
[1, 2, 3, 4, 5, 6], | |
(v) => v % 2 === 0 ? 'even': 'odd' | |
) | |
); |
Thank you!
I also update to check first if no defined to avoid forget it as I did in my project 😅
For Safari, you need to use Array.prototype.groupToMap
.
And you could also add another check for Array.prototype.group
.
const hasGroup = typeof Object.groupBy === typeof undefined || typeof Array.groupToMap === typeof undefined || typeof Array.group === typeof undefined;
if (!hasGroup) {
const groupBy = (arr, callback) => {
return arr.reduce((acc = {}, ...args) => {
const key = callback(...args);
acc[key] ??= []
acc[key].push(args[0]);
return acc;
}, {});
};
if (typeof Object.groupBy === typeof undefined) {
Object.groupBy = groupBy;
}
if (typeof Array.groupToMap === typeof undefined) {
Array.groupToMap = groupBy;
}
if (typeof Array.group === typeof undefined) {
Array.group = groupBy;
}
}
I would do it in this way @jdegand
Thanks for the info =)
I think the code should negate the hasGroup
condition:
const noGroup = ....
if(noGroup) {
}
As we're checking for undefined.
In other words:
const noGroup = typeof Object.groupBy === typeof undefined || typeof Array.groupToMap === typeof undefined || typeof Array.group === typeof undefined;
if (noGroup) {
const groupBy = (arr, callback) => {
return arr.reduce((acc = {}, ...args) => {
const key = callback(...args);
acc[key] ??= []
acc[key].push(args[0]);
return acc;
}, {});
};
if (typeof Object.groupBy === typeof undefined) {
Object.groupBy = groupBy;
}
if (typeof Array.groupToMap === typeof undefined) {
Array.groupToMap = groupBy;
}
if (typeof Array.group === typeof undefined) {
Array.group = groupBy;
}
}
if (typeof Object.groupBy === typeof undefined) {
Object.groupBy = groupBy;
}
This can be omitted because at least first condition must match to be inside the first if.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The original API is without prototype. Link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy
Here is basic usage from documentation:
Anyway, by removing
prototype
your code works very well. I have used it as a polyfill for Google Chrome >= v116.