You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

修改说明

  1. 返回类型调整:从string[]改为Record<string, Person[]>,明确返回值是键为字符串、值为Person数组的对象
  2. 回调类型扩展:允许回调返回string | number,支持数字类型的分组键(如出生年份),并通过String()统一转为字符串作为对象键
  3. 分组逻辑重构:遍历每个Person对象,根据回调获取的键维护分组数组,将对象归类到对应组中

验证示例

运行修改后的代码,调用groupBy(input, (p) => p.placeOfBirth)和groupBy(input, (p) => p.yearOfBirth),即可得到预期的分组结果。

内容的提问来源于stack exchange,提问作者Jameson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 09:35:11