JavaScript合并对象数组重复项并聚合修改指定属性
JavaScript 自定义规则合并对象数组重复项(酒店预订场景)
需求背景
处理Excel导入的酒店预订记录数组,每条记录通过reservationNumber作为唯一预订标识:当数组中存在2条及以上相同reservationNumber的记录时,代表该预订包含多间客房,需按指定规则合并为单条记录。原有基于Map实现的简单合并方法仅支持属性覆盖,无法满足定制化聚合要求。
合并规则
- 同组第一条记录作为主记录,保留其
roomNumber作为主房号,姓名、证件信息、酒店编码、代理商编码、mainRoomDistribution等基础属性直接沿用主记录值 - 组内其余重复记录的
roomNumber聚合到extra_rooms数组,存储除主房外的所有附加房号 - 组内其余重复记录的客房入住信息聚合到
extraRoomsAges数组,单个元素格式为{room: 房号, adults: 成人数, infants: 婴儿数}:其中room取自对应记录的roomNumber,adults、infants取自对应记录的mainRoomDistribution属性 - 合并后记录的
totalCharges为同组所有记录的费用总和
实现代码
function mergeHotelReservations(records) { const resMap = new Map(); for (const item of records) { const resNo = item.reservationNumber; // 首次命中预订号,初始化合并后的主记录结构 if (!resMap.has(resNo)) { resMap.set(resNo, { ...item, extra_rooms: [], extraRoomsAges: [], totalCharges: item.totalCharges }); continue; } // 处理同预订号的后续记录,仅更新聚合字段 const current = resMap.get(resNo); current.extra_rooms.push(item.roomNumber); current.extraRoomsAges.push({ room: item.roomNumber, adults: item.mainRoomDistribution.adults, infants: item.mainRoomDistribution.infants }); current.totalCharges += item.totalCharges; } return Array.from(resMap.values()); }
实现逻辑说明
- 选用
Map作为分组存储结构:相比普通对象,Map严格遵循插入顺序遍历,可保证最终输出的记录顺序与原始数据中预订号首次出现的顺序一致,且不存在原型链属性污染问题。 - 遍历过程中对首次出现的预订号,直接展开第一条记录的所有属性作为合并后记录的基础值,同时初始化需要聚合的数组字段与总费用字段,避免后续聚合操作出现属性未定义的报错。
- 对同预订号的非首条记录,不修改已有的基础属性,仅执行三类聚合操作:向
extra_rooms追加房号、组装入住信息对象推入extraRoomsAges数组、累加totalCharges。 - 遍历完成后通过
Array.from()将Map中存储的合并结果转为标准数组返回。
鲁棒性优化提示:如果原始导入数据存在字段缺失情况,可在取值时增加可选链与默认值,例如将
item.mainRoomDistribution.adults替换为item.mainRoomDistribution?.adults ?? 0,避免空值抛出异常。
内容的提问来源于stack exchange,提问作者NaturalDevCR
相关产品推荐
相关产品推荐

