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

JavaScript按属性名拆分对象数组并分组去重的实现方法

联表查询结果数组按角色分组去重实现

需求说明

  • 输入为SQL联表查询返回的对象数组,单条记录包含多组角色的ID、名称字段,字段命名规则固定为id_{角色名}、{角色名}_name
  • 输出需满足三个规则:
    • 按角色名拆分分组,每个角色对应独立数组
    • 单条分组记录仅保留对应角色的ID、名称两个属性
    • 同角色下ID与名称完全一致的重复条目仅保留1次

原始输入数据

let personArray = [
    {
        id_dentist: 1,
        dentist_name: 'John',
        id_secretary: 6,
        secretary_name: 'Paul',
        id_security: 3,
        security_name: 'Carl'
    },
    {
        id_dentist: 2,
        dentist_name: 'Lisa',
        id_secretary: 9,
        secretary_name: 'Beth',
        id_security: 5,
        security_name: 'Monica'
    },
    {
        id_dentist: 1,
        dentist_name: 'John',
        id_secretary: 6,
        secretary_name: 'Paul',
        id_security: 3,
        security_name: 'Carl'
    }
];

期望输出结构

let personObject = {
    dentist: [
        { id_dentist: 1, dentist_name: 'John' },
        { id_dentist: 2, dentist_name: 'Lisa' },
    ],
    secretary: [
        { id_secretary: 6, secretary_name: 'Paul' },
        { id_secretary: 9, secretary_name: 'Beth' },
    ],
    security: [
        { id_security: 3, security_name: 'Carl' },
        { id_security: 5, security_name: 'Monica' }
    ]
};

原有代码问题

之前编写的逻辑存在两处核心错误,导致结果不符合预期:

  1. 仅提取了单条记录中第一个匹配id_前缀的字段作为分组key,同一条记录里的其余角色字段完全被遗漏
  2. 直接将整条原始记录推入分组数组,既没有提取对应角色的专属字段,也没有做重复条目校验
    原有错误代码如下:
const obj = personArray.reduce((acc, cur) => {
    const key = Object.keys(cur).filter(f => /^id_/.test(f))[0].split('_')[1];
    if (!acc[key]) acc[key] = [];
    acc[key].push(cur);
    return acc;
}, {});

console.log(obj);

可直接运行的实现代码

遍历过程中逐个提取单条记录内的所有角色字段,用临时Set结构记录已存在的ID+名称组合实现去重,最终清理临时属性即可得到目标结果:

const personObject = personArray.reduce((acc, cur) => {
    // 遍历当前记录所有id前缀的字段,覆盖全部角色
    Object.keys(cur).filter(key => key.startsWith('id_')).forEach(idKey => {
        const role = idKey.split('_')[1];
        const nameKey = `${role}_name`;
        const entry = {
            [idKey]: cur[idKey],
            [nameKey]: cur[nameKey]
        };
        // 初始化分组数组和去重用的集合
        if (!acc[role]) {
            acc[role] = [];
            acc[`_${role}_set`] = new Set();
        }
        // 拼接id和名称作为去重唯一标识
        const uniqueMark = `${cur[idKey]}||${cur[nameKey]}`;
        if (!acc[`_${role}_set`].has(uniqueMark)) {
            acc[`_${role}_set`].add(uniqueMark);
            acc[role].push(entry);
        }
    });
    return acc;
}, {});

// 删除遍历过程中生成的临时去重属性
Object.keys(personObject).forEach(key => {
    if (key.startsWith('_')) delete personObject[key];
});

console.log(personObject);

该实现自动适配命名符合规则的新增角色字段,后续联表查询新增角色类型时无需修改代码逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:12:30