Array grouping method
ECMAScript 15 Array Grouping Methods
ECMAScript 15 introduces new array grouping methods group
and groupToMap
, which allow grouping array elements based on specified conditions, returning an object or Map where the keys are the grouping criteria and the values are the corresponding arrays of elements.
Array.prototype.group
The group
method takes a callback function as an argument. This callback function receives the current element, index, and the array itself, and returns a string as the grouping key. The method ultimately returns an object where the properties are the grouping keys and the values are the corresponding arrays of elements.
const inventory = [
{ name: 'asparagus', type: 'vegetables', quantity: 5 },
{ name: 'bananas', type: 'fruit', quantity: 0 },
{ name: 'goat', type: 'meat', quantity: 23 },
{ name: 'cherries', type: 'fruit', quantity: 5 },
{ name: 'fish', type: 'meat', quantity: 22 }
];
const result = inventory.group(({ type }) => type);
console.log(result);
/*
{
vegetables: [
{ name: 'asparagus', type: 'vegetables', quantity: 5 }
],
fruit: [
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "cherries", type: "fruit", quantity: 5 }
],
meat: [
{ name: "goat", type: "meat", quantity: 23 },
{ name: "fish", type: "meat", quantity: 22 }
]
}
*/
Array.prototype.groupToMap
The groupToMap
method is similar to group
but returns a Map object instead of a plain object. This is particularly useful when the grouping key is not a string, as Map keys can be any value.
const inventory = [
{ name: 'asparagus', type: 'vegetables', quantity: 5 },
{ name: 'bananas', type: 'fruit', quantity: 0 },
{ name: 'goat', type: 'meat', quantity: 23 },
{ name: 'cherries', type: 'fruit', quantity: 5 },
{ name: 'fish', type: 'meat', quantity: 22 }
];
const result = inventory.groupToMap(({ quantity }) =>
quantity < 5 ? 'restock' : 'adequate'
);
console.log(result);
/*
Map {
'adequate' => [
{ name: 'asparagus', type: 'vegetables', quantity: 5 },
{ name: 'goat', type: 'meat', quantity: 23 },
{ name: 'cherries', type: 'fruit', quantity: 5 },
{ name: 'fish', type: 'meat', quantity: 22 }
],
'restock' => [
{ name: 'bananas', type: 'fruit', quantity: 0 }
]
}
*/
Complex Grouping Example
The grouping methods can handle more complex grouping logic, such as grouping based on multiple conditions:
const people = [
{ name: 'Alice', age: 21, city: 'New York' },
{ name: 'Bob', age: 24, city: 'Chicago' },
{ name: 'Charlie', age: 21, city: 'New York' },
{ name: 'Dave', age: 24, city: 'Chicago' },
{ name: 'Eve', age: 30, city: 'Los Angeles' }
];
const grouped = people.group(({ age, city }) => `${age}-${city}`);
console.log(grouped);
/*
{
'21-New York': [
{ name: 'Alice', age: 21, city: 'New York' },
{ name: 'Charlie', age: 21, city: 'New York' }
],
'24-Chicago': [
{ name: 'Bob', age: 24, city: 'Chicago' },
{ name: 'Dave', age: 24, city: 'Chicago' }
],
'30-Los Angeles': [
{ name: 'Eve', age: 30, city: 'Los Angeles' }
]
}
*/
Performance Considerations
For large arrays, the performance of grouping operations is important. The group
and groupToMap
methods are internally optimized and generally perform better than manually implemented equivalent code:
// Manual grouping implementation
function manualGroup(array, keyFn) {
const result = {};
for (const item of array) {
const key = keyFn(item);
if (!result[key]) {
result[key] = [];
}
result[key].push(item);
}
return result;
}
// Using built-in methods
const largeArray = Array(1000000).fill().map((_, i) => ({
id: i,
category: i % 10
}));
console.time('built-in');
largeArray.group(x => x.category);
console.timeEnd('built-in');
console.time('manual');
manualGroup(largeArray, x => x.category);
console.timeEnd('manual');
Browser Compatibility
As of 2023, the group
and groupToMap
methods are implemented in the latest versions of major browsers, but older browsers may require a polyfill:
if (!Array.prototype.group) {
Array.prototype.group = function(callback) {
return this.reduce((acc, item, index, array) => {
const key = callback(item, index, array);
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(item);
return acc;
}, {});
};
}
if (!Array.prototype.groupToMap) {
Array.prototype.groupToMap = function(callback) {
return this.reduce((acc, item, index, array) => {
const key = callback(item, index, array);
if (!acc.has(key)) {
acc.set(key, []);
}
acc.get(key).push(item);
return acc;
}, new Map());
};
}
Combining with Other Array Methods
Grouping methods can be chained with other array methods to create powerful data processing pipelines:
const products = [
{ id: 1, name: 'Laptop', category: 'Electronics', price: 999 },
{ id: 2, name: 'Smartphone', category: 'Electronics', price: 699 },
{ id: 3, name: 'Desk', category: 'Furniture', price: 299 },
{ id: 4, name: 'Chair', category: 'Furniture', price: 199 },
{ id: 5, name: 'Monitor', category: 'Electronics', price: 399 }
];
const result = products
.filter(product => product.price > 200)
.group(product => product.category);
console.log(result);
/*
{
Electronics: [
{ id: 1, name: 'Laptop', category: 'Electronics', price: 999 },
{ id: 2, name: 'Smartphone', category: 'Electronics', price: 699 },
{ id: 5, name: 'Monitor', category: 'Electronics', price: 399 }
],
Furniture: [
{ id: 3, name: 'Desk', category: 'Furniture', price: 299 }
]
}
*/
Practical Use Cases
Grouping methods are highly useful in data processing and presentation, especially when organizing data by categories:
// Data processing before visualization
const salesData = [
{ month: 'January', product: 'Widget A', sales: 100 },
{ month: 'January', product: 'Widget B', sales: 150 },
{ month: 'February', product: 'Widget A', sales: 200 },
{ month: 'February', product: 'Widget B', sales: 175 },
{ month: 'March', product: 'Widget A', sales: 120 },
{ month: 'March', product: 'Widget B', sales: 140 }
];
// Group by month
const byMonth = salesData.group(item => item.month);
// Group by product
const byProduct = salesData.group(item => item.product);
// Create chart data
const chartData = Object.entries(byMonth).map(([month, items]) => ({
month,
totalSales: items.reduce((sum, item) => sum + item.sales, 0)
}));
console.log(chartData);
/*
[
{ month: 'January', totalSales: 250 },
{ month: 'February', totalSales: 375 },
{ month: 'March', totalSales: 260 }
]
*/
Relationship with Object.groupBy and Map.groupBy
ECMAScript 15 also introduces static methods Object.groupBy
and Map.groupBy
, which function similarly to the instance methods but can be used with any iterable object:
const arrayLike = {
length: 3,
0: { name: 'Alice', age: 21 },
1: { name: 'Bob', age: 24 },
2: { name: 'Charlie', age: 21 }
};
const grouped = Object.groupBy(arrayLike, ({ age }) => age > 21 ? 'over21' : 'under22');
console.log(grouped);
/*
{
under22: [
{ name: 'Alice', age: 21 },
{ name: 'Charlie', age: 21 }
],
over21: [
{ name: 'Bob', age: 24 }
]
}
*/
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn