TypeScript中如何实现基于回调函数的JSON数据分组功能
实现TypeScript的groupBy分组函数
需求说明
需要编写一个groupBy函数,通过传入的回调函数对Person对象数组进行分组,根据回调返回的键值将对象归类到对应组中。
定义的Person接口与输入数据
interface Person { name: string; yearOfBirth: number; placeOfBirth: string; } const input: Person[] = [ { name: "Andy", yearOfBirth: 1984, placeOfBirth: "New York", }, { name: "John", yearOfBirth: 1995, placeOfBirth: "New York", }, { name: "Bill", yearOfBirth: 1995, placeOfBirth: "Orlando", }, { name: "Tim", yearOfBirth: 1989, placeOfBirth: "Witchita", }, ];
当前问题代码
现有代码仅能返回分组键的数组,无法实现预期的分组功能:
const groupBy = (input: Person[], func: (p: Person) => string): string[] => { let collect: string[] = []; for (let i = 0; i < input.length; i++) { collect[i] = func(input[i]); } return collect; } try { console.log(groupBy(input, (p: Person) => p.placeOfBirth)); } catch (e: any) { console.log(e.message); } // 当前输出: // [ 'New York', 'New York', 'Orlando', 'Witchita' ]
预期输出
- 按出生地分组:
console.log(groupBy(input, (p: Person) => p.placeOfBirth)); // 预期输出: { "New York": [ { name: 'Andy', yearOfBirth: 1984, placeOfBirth: 'New York' }, { name: 'John', yearOfBirth: 1995, placeOfBirth: 'New York' } ], "Orlando": [ { name: 'Bill', yearOfBirth: 1995, placeOfBirth: 'Orlando' } ], "Witchita": [ { name: 'Tim', yearOfBirth: 1989, placeOfBirth: 'Witchita' } ] }
- 按出生年份分组:
console.log(groupBy(input, (p: Person) => p.yearOfBirth)); // 预期输出: { "1984": [ { name: 'Andy', yearOfBirth: 1984, placeOfBirth: 'New York' } ], "1995": [ { name: 'John', yearOfBirth: 1995, placeOfBirth: 'New York' }, { name: 'Bill', yearOfBirth: 1995, placeOfBirth: 'Orlando' } ], "1989": [ { name: 'Tim', yearOfBirth: 1989, placeOfBirth: 'Witchita' } ] }
解决方案
修改groupBy函数,使其构建分组对象而非仅收集键数组,同时适配不同类型的分组键:
const groupBy = (input: Person[], func: (p: Person) => string | number): Record<string, Person[]> => { const result: Record<string, Person[]> = {}; for (const person of input) { // 将回调返回的键统一转为字符串,避免数字键的类型问题 const key = String(func(person)); // 若当前键未初始化分组数组,先创建空数组 if (!result[key]) { result[key] = []; } // 将当前Person对象推入对应分组数组 result[key].push(person); } return result; };
修改说明
- 返回类型调整:从
string[]改为Record<string, Person[]>,明确返回值是键为字符串、值为Person数组的对象 - 回调类型扩展:允许回调返回
string | number,支持数字类型的分组键(如出生年份),并通过String()统一转为字符串作为对象键 - 分组逻辑重构:遍历每个Person对象,根据回调获取的键维护分组数组,将对象归类到对应组中
验证示例
运行修改后的代码,调用groupBy(input, (p) => p.placeOfBirth)和groupBy(input, (p) => p.yearOfBirth),即可得到预期的分组结果。
内容的提问来源于stack exchange,提问作者Jameson
相关产品推荐
相关产品推荐

