ES2024系列 - Map.groupBy() 数组分组聚合

209 阅读3分钟

我在另一篇文章中讲了Object.groupBy()数组分组聚合,Map.groupBy()和它很相似,只不过前一个返回的是POJO普通对象,而后一个返回的是Map类型对象。

新特性解决的问题

我们在处理数据库返回的数据时,时常要做各种分组聚合,举例如下:

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 },
];

假如现在数据库中存储了上述的各种不同的食物名称、分类和数量。

现在UI界面要求把需要补充库存的和不需要补充库存的分开显示。

我们可能需要这样一个数据结构:

{
	{ restock: true }:  [
		{ name: 'bananas', type: 'fruit', quantity: 5 }
	],
	{ restock: false }: [
		{ name: 'asparagus', type: 'vegetables', quantity: 9 },
		{ name: 'goat', type: 'meat', quantity: 23 },
		{ name: 'cherries', type: 'fruit', quantity: 12 },
		{ name: 'fish', type: 'meat', quantity: 22 }
	]
}

restock这个单词是需要重新进货的意思。 这里比较特殊的是对象的键名也是对象,很显然我们普通的JavaScript对象无法满足这种结构。这时就需要Map出场了,Map最大的特点就是键名可以是对象,而普通对象的键名只能是字符串或者Symbol。

下面我们来看看Map.groupBy是怎么解决问题的:

const restock = { restock: true,  };
const sufficient = { restock: false };
const result = Map.groupBy(inventory, ({ quantity }) =>
  quantity < 6 ? restock : sufficient,
);
// [{ name: "bananas", type: "fruit", quantity: 5 }]
console.log(result.get(restock));
// 打印结果看下图
console.log(result);

Map.groupBy的返回值

例子中可以看到restocksufficient对象在Map.groupBy的回调函数中被返回,成为了result的键名,inventory数组中quantity小于6的和大于6的都汇聚成了数组分别成为了result的键值。

这就是新特性:Map.groupBy

Map.groupBy

从上面的例子可以看出,Map.groupBy可以对目标数据集进行分组聚合。

下面咱们来看一下它的具体用法。

语法

Map.groupBy(items, callbackFn)

参数

items

第一个参数items代表需要处理的可迭代对象,例如:数组。

callbackFn

第二个参数callbackFn代表callback函数。

callbackFn函数的参数: 1. element:数组中的元素。 2. indexelement的数组索引。

callbackFn的返回值规则:

callbackFn必须有返回值,每个返回值都会作为最终返回的Map对象的键名。如果多条数据的键名相同,则其值以数组的形式叠加起来。 返回值可以是对象也可以是基本类型(null也是可以的),其规则和Map类型的键名规则一致。这一点相当灵活。 如果没有返回值,那undefined会被作为返回值。

返回值

返回值是一个Map对象,对象的键名是callbackFn函数的返回值,键值是每个callbackFn函数的返回值所对应的数组项组成的数组。

所以说Map.groupBy做的事就是对目标数组进行分组。

语言解释确实比较困难且难懂,大家最好结合上面的例子,就什么都明白了。

浏览器兼容性

目前该特性已经到了 Stage 4 阶段,欲了解 Stage 4 的含义可以看这篇文章 各大主流浏览器也是刚刚开始支持。

其实Map.groupByObject.groupBy同属一个ECMAScript提案,它们都是为了更好的处理数组。

Polyfill

corejs已经有对应的Polyfill。

结束语

ES2024系列专辑将持续更新将在2024年发布的新特性。敬请关注!

注:以上例子部分参考了MDN