前言
array group by 是一个很常见的功能. 但 JS 却没有 build-in 方法. 一直到 es2023 才有 group 和 groupToMap (目前没有任何游览器支持, 但已经有 polyfill 了).
这篇来聊一聊这个.
参考
Stack Overflow – Most efficient method to groupby on an array of objects (用 reduce 实现的 group by, 也是最 popular 的方案)
Setup
目前游览器不支持, 要 test 需要安装 core.js
yarn add core-js
然后 import, 然后 declare TypeScript
import 'core-js/actual/array/group'; import 'core-js/actual/array/group-to-map'; declare global { interface Array<T> { group<GroupKey extends string | symbol>( callbackfn: (this: T[], item: T, index: number, array: T[]) => GroupKey ): Record<GroupKey, T[]>; groupToMap<GroupKey>( callbackfn: (this: T[], item: T, index: number, array: T[]) => GroupKey ): Map<GroupKey, T[]>; } }
Array.group
group<GroupKey extends string | symbol>( callbackfn: (this: T[], item: T, index: number, array: T[]) => GroupKey ): Record<GroupKey, T[]>;
group 的用法很简单, 给一个 callbackfn, 返回一个 key. 它会把相同 key 的 item group 在一起.
最终返回一个对象, 对象的 key 就是 group by 的 key, value 则是相同 key 的所有 items.
例子: group by name
const items = [ { name: 'Derrick', age: 1 }, { name: 'Peter', age: 1 }, { name: 'Derrick', age: 2 }, { name: 'Peter', age: 2 }, ]; const result = items.group(item => item.name); console.log(JSON.stringify(result, null, 2));
结果
注意: key 只能是 string or symbol. 其它的都不可以, 包括 number, 如果 callbackfn 返回不是 string | symbol 会被强转成 string.
Array.groupToMap
groupToMap<GroupKey>( callbackfn: (this: T[], item: T, index: number, array: T[]) => GroupKey ): Map<GroupKey, T[]>;
它和 group 差不多. 只是 group key 不强制是 string | symbol. 可以返回任何类型.
因为 groupToMap 返回的结果不是 object, 而是 Map. 而我们知道 Map 的 key 可以是任何类型.
const items = [ { name: 'Derrick', age: 1 }, { name: 'Peter', age: 1 }, { name: 'Derrick', age: 2 }, { name: 'Peter', age: 2 }, ]; const result = items.groupToMap(item => item.name); for (const [key, value] of result) { // 1. ['Derrick', [{ name: 'Derrick', age: 1 }, { name: 'Derrick', age: 2 }]] // 2. ['Peter', [{ name: 'Peter', age: 1 }, { name: 'Peter', age: 2 }]] console.log([key, value]); }
How it compare?
group by 的关键之一就是 group key 的 comparison.
比如我 fetch 获取一些资料, 然后想 group by Date.
这时候如果用 group 的话, 它会先把 Date 转成 string 然后通过 === 来 compare.
如果是 groupToMap 则是直接用 === 来 compare. 这时就危险了. 因为 Date 是对象 === 比的是指针是否相同, 而不是 date time value 是否相同.
所以在使用 group 或 groupToMap 要注意 group key 的类型哦.
multiple group key
C# LINQ GroupBy 支持 multiple group key
items.GroupBy(item => new { item.Name, item.Age }).ToList()
但 JS 没有这个功能. 而且也没有简单的手法可以利用 group | groupToMap 去实现这个功能.
标签:group,name,age,JavaScript,groupToMap,item,GroupToMap,key,Group From: https://www.cnblogs.com/keatkeat/p/17068291.html