diff --git a/README.md b/README.md index 6fa8c9f..f9b8b8a 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ pnpm add @utopia-utils/dom * pipe: 函数组合, 从左到右执行。[source](https://github.com/GreatAuk/utopia-utils/blob/main/packages/core/src/pipe.ts) * onlyResolvesLast: 解决竞态问题,只保留最后一次调用的结果。[source](https://github.com/GreatAuk/utopia-utils/blob/main/packages/core/src/onlyResolvesLast.ts) * parseQuery: 解析 url query。[source](https://github.com/GreatAuk/utopia-utils/blob/main/packages/core/src/parseQuery.ts) +* groupBy: 数组根据指定的 key 分组。[source](https://github.com/GreatAuk/utopia-utils/blob/main/packages/core/src/groupBy.ts) ### 类型判断 ```bash diff --git a/packages/core/src/groupBy.test.ts b/packages/core/src/groupBy.test.ts new file mode 100644 index 0000000..29ddf6e --- /dev/null +++ b/packages/core/src/groupBy.test.ts @@ -0,0 +1,27 @@ +import { groupBy } from './groupBy' + +describe('groupBy', () => { + it('should group by a string', () => { + const array = [ + { name: 'John', age: 20 }, + { name: 'Jane', age: 25 }, + { name: 'Jack', age: 20 }, + ] + + const result = groupBy(array, item => `${item.age}`) + expect(result).toEqual({ + 20: [ + { name: 'John', age: 20 }, + { name: 'Jack', age: 20 }, + ], + 25: [{ name: 'Jane', age: 25 }], + }) + + const arr2 = [4.2, 6.3, 6.5] + const result2 = groupBy(arr2, v => `${Math.floor(v)}`) + expect(result2).toEqual({ + 4: [4.2], + 6: [6.3, 6.5], + }) + }) +}) diff --git a/packages/core/src/groupBy.ts b/packages/core/src/groupBy.ts new file mode 100644 index 0000000..f3cbd64 --- /dev/null +++ b/packages/core/src/groupBy.ts @@ -0,0 +1,25 @@ +/** + * group an array by a string + * @param {T[]} array - The array to iterate over. + * @param iteratee - (item: T) => string + * @returns {Record} Returns the composed aggregate object. + * @example + * ``` + groupBy([4.2, 6.3, 6.5], v => `${Math.floor(v)}`) + // { '4': [ 4.2 ], '6': [ 6.3, 6.5 ] } + + groupBy([{ name: 'John', age: 20 }, { name: 'Jane', age: 25 }], item => `${item.age}`) + // { '20': [ { name: 'John', age: 20 } ], '25': [ { name: 'Jane', age: 25 } ] } + * ``` + */ +export function groupBy(array: T[], iteratee: (item: T) => string): Record { + return array.reduce>((acc, item) => { + const key = iteratee(item) + if (acc[key]) + acc[key].push(item) + else + acc[key] = [item] + + return acc + }, {}) +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 5723235..fecbbdf 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -16,6 +16,7 @@ export * from './escapeStringRegexp' export * from './getByPath' export * from './getFileName' export * from './getQueryParams' +export * from './groupBy' export * from './intersection' export * from './math' export * from './memoize'