如何用reduce匹配数组groupPoint属性并替换数据?问题修复
合并数组并按groupPoint覆盖数据的问题
需求
有两个数组initialData和data,需要合并成一个数组:当元素的groupPoint属性匹配时,采用data数组中的对应数据,最终保留initialData的原有顺序。
初始数据
const initialData = [ {groupPoint: '00:00', soldLeads: 0}, {groupPoint: '01:00', soldLeads: 0}, {groupPoint: '02:00', soldLeads: 0}, {groupPoint: '03:00', soldLeads: 0}, {groupPoint: '04:00', soldLeads: 0}, {groupPoint: '05:00', soldLeads: 0}, {groupPoint: '06:00', soldLeads: 0}, {groupPoint: '07:00', soldLeads: 0}, {groupPoint: '08:00', soldLeads: 0}, {groupPoint: '09:00', soldLeads: 0}, {groupPoint: '10:00', soldLeads: 0}, ] const data = [ {groupPoint: '03:00', soldLeads: '4'}, {groupPoint: '04:00', soldLeads: '1'}, {groupPoint: '07:00', soldLeads: '1'} ]
预期结果
const result = [ {groupPoint: '00:00', soldLeads: 0}, {groupPoint: '01:00', soldLeads: 0}, {groupPoint: '02:00', soldLeads: 0}, {groupPoint: '03:00', soldLeads: '4'}, {groupPoint: '04:00', soldLeads: '1'}, {groupPoint: '05:00', soldLeads: 0}, {groupPoint: '06:00', soldLeads: 0}, {groupPoint: '07:00', soldLeads: '1'}, {groupPoint: '08:00', soldLeads: 0}, {groupPoint: '09:00', soldLeads: 0}, {groupPoint: '10:00', soldLeads: 0}, ]
注:原预期结果中
04:00和08:00的值存在错误,此处已根据data内容修正为正确结果。
实际错误结果
运行现有代码后出现重复元素,部分groupPoint对应的元素被重复添加:
const wrongResult = [ {groupPoint: '00:00', soldLeads: 0}, {groupPoint: '01:00', soldLeads: 0}, {groupPoint: '02:00', soldLeads: 0}, {groupPoint: '03:00', soldLeads: '4'}, {groupPoint: '03:00', soldLeads: 0}, {groupPoint: '04:00', soldLeads: 0}, {groupPoint: '05:00', soldLeads: 0}, {groupPoint: '06:00', soldLeads: 0}, {groupPoint: '07:00', soldLeads: '4'}, {groupPoint: '07:00', soldLeads: 0}, {groupPoint: '08:00', soldLeads: '1'}, {groupPoint: '08:00', soldLeads: 0}, {groupPoint: '09:00', soldLeads: 0}, {groupPoint: '10:00', soldLeads: 0}, ]
当前代码
const result = initialData.reduce((acc, categoryItem, idx) => { return [ ...acc, ...data .map((dataItem, index) => { if (categoryItem.groupPoint === dataItem.groupPoint) { return { groupPoint: dataItem.groupPoint, ...dataItem, }; } if (index === data.length - 1 && !acc[idx]) { return { ...categoryItem }; } }) .filter(Boolean), ]; }, []);
问题分析
现有代码的核心问题:
- 遍历
initialData的每个元素时,都对整个data数组执行map操作,导致匹配到的元素被添加一次后,当data遍历到最后一个元素时,又会因为!acc[idx]的错误判断,再次添加原categoryItem。 acc[idx]的逻辑完全错误——acc是累积的结果数组,其长度随迭代不断增加,和initialData的索引idx并不对应,无法准确判断元素是否已被添加。
正确实现(基于reduce)
先将data转换为以groupPoint为键的映射表,实现O(1)时间查找,再用reduce遍历生成结果:
// 把data转成映射表,提升查找效率 const dataMap = data.reduce((map, item) => { map[item.groupPoint] = item; return map; }, {}); // 用reduce合并数组 const result = initialData.reduce((acc, item) => { // 优先使用data中匹配的元素,无匹配则保留原元素 const mergedItem = dataMap[item.groupPoint] || item; acc.push(mergedItem); return acc; }, []);
如果想在单次reduce中实现(适合数据量较小的场景):
const result = initialData.reduce((acc, item) => { // 查找data中是否有匹配的groupPoint元素 const match = data.find(dataItem => dataItem.groupPoint === item.groupPoint); acc.push(match || item); return acc; }, []);
内容的提问来源于stack exchange,提问作者Kate
相关产品推荐
相关产品推荐

