JavaScript按eventId合并分块Person对象数组实现方法
问题描述
你定义了两类基础数据结构:
Person { name: string birthday: Date lifeEvents: LifeEvent[] } LifeEvent { eventId: number message: string comments: string }
分块传输拿到的Person数组存在以下特征:
- 数组内仅存在1个父级Person对象,
name、birthday字段有有效值,lifeEvents字段为空或null - 其余所有对象的
name、birthday字段均为null/未赋值,每个对象仅包含1个LifeEvent条目 - 单个LifeEvent条目要么携带
eventId + message有效值,要么携带eventId + comments有效值
需求为:提取父级Person对象,收集所有分散的LifeEvent条目,将相同eventId的条目合并为完整的LifeEvent对象,存入父对象的lifeEvents数组,最终输出1个结构完整、lifeEvents已按eventId完成全量合并的Person对象。
提供的示例数据如下:
let results = [ { name: 'Test1', birthday: '2022-06-14', lifeEvents: null }, { name: null, birthday: null, lifeEvents: [ { eventId: 1, message: 'First event', comments: null } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 2, message: 'Second event', comments: null } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 1, message: null, comments: 'First event comment' } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 2, message: null, comments: 'Second event comment' } ] }, ]
实现方案
核心逻辑分三步:
- 从数组中筛选出带有效
name字段的父级Person对象,做浅拷贝避免修改原数据 - 遍历数组其余对象,提取每个对象内的LifeEvent条目,以
eventId为key存入Map做合并:遇到已存在的eventId,就把当前条目的非空字段补到已存对象上 - 将Map中合并完成的所有LifeEvent转为数组,赋值给父对象的
lifeEvents字段即可
完整可运行代码:
function mergePersonResults(results) { // 提取父级Person对象 const parentPerson = {...results.find(item => item.name !== null)}; // 用Map暂存合并过程中的LifeEvent,key为eventId const eventMap = new Map(); // 遍历所有条目收集、合并LifeEvent results.forEach(item => { // 跳过无有效lifeEvents的条目(包含父级对象) if (!item.lifeEvents?.length) return; const currentEvent = item.lifeEvents[0]; const eventId = currentEvent.eventId; if (eventMap.has(eventId)) { // 存在同id事件,合并非空字段,不覆盖已有有效值 const existingEvent = eventMap.get(eventId); existingEvent.message = existingEvent.message ?? currentEvent.message; existingEvent.comments = existingEvent.comments ?? currentEvent.comments; } else { // 不存在同id事件,浅拷贝后存入Map eventMap.set(eventId, {...currentEvent}); } }); // 组装最终结果 parentPerson.lifeEvents = Array.from(eventMap.values()); return parentPerson; } // 测试示例数据 const mergedResult = mergePersonResults(results); console.log(mergedResult);
处理示例数据的输出结果如下:
{ name: 'Test1', birthday: '2022-06-14', lifeEvents: [ { eventId: 1, message: 'First event', comments: 'First event comment' }, { eventId: 2, message: 'Second event', comments: 'Second event comment' } ] }
说明:代码中使用空值合并运算符
??,仅在左侧值为null/undefined时取右侧值,避免覆盖已存在的有效字段;如果需要兼容更低版本JS运行环境,可将??替换为||,替换前需确认业务中不存在空字符串这类假值需要保留的场景。
内容的提问来源于stack exchange,提问作者Wagner D'Amaral
相关产品推荐
相关产品推荐

