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' } ] };
原有代码问题
之前编写的逻辑存在两处核心错误,导致结果不符合预期:
- 仅提取了单条记录中第一个匹配
id_前缀的字段作为分组key,同一条记录里的其余角色字段完全被遗漏 - 直接将整条原始记录推入分组数组,既没有提取对应角色的专属字段,也没有做重复条目校验
原有错误代码如下:
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
相关产品推荐
相关产品推荐

