如何使用reduce创建含重复键的对象数组
数据结构转换问题解决
问题背景
现有如下结构的对象数组:
const data = [ { "date": "2020-01-02", "run": [ {"time": "1", "result": 100}, {"time": "2", "result": 150}, {"time": "3", "result": 92} ] }, { "date": "2020-01-15", "run": [ {"time": "1", "result": 90}, {"time": "2", "result": 86}, {"time": "3", "result": 133} ] }, { "date": "2020-02-11", "run": [ {"time": "1", "result": 45}, {"time": "2", "result": 176}, {"time": "3", "result": 108} ] }, ]
需要转换为以下结构:
[ { "time": 1, "2020-01-02": 100, "2020-01-15": 90, "2020-02-11": 45 }, { "time": 2, "2020-01-02": 150, "2020-01-15": 86, "2020-02-11": 176 }, { "time": 3, "2020-01-02": 92, "2020-01-15": 133, "2020-02-11": 108 }, ]
原代码问题分析
你之前的reduce代码存在几个关键问题:
- 初始值设置错误,仅提取了第一个日期的第一个运行结果,未覆盖所有time项
- reduce返回逻辑错误,最终得到单个混乱对象而非目标数组,且错误使用
currIdx-1索引run项,导致取值错位 - 未遍历每个
run数组,无法完整收集每个time对应的多日期结果
正确实现方案
我们可以通过按time分组收集数据,再转换为目标数组的方式完成需求:
// 构建以time为键的映射对象,收集对应日期的结果 const timeMap = data.reduce((map, item) => { const currentDate = item.date; // 遍历当前日期下的所有运行记录 item.run.forEach(run => { const timeNum = parseInt(run.time); // 初始化该time对应的对象(如果不存在) if (!map[timeNum]) { map[timeNum] = { time: timeNum }; } // 为该time对象添加当前日期的结果 map[timeNum][currentDate] = run.result; }); return map; }, {}); // 将映射对象的值转换为数组,得到最终结果 const finalResult = Object.values(timeMap); console.log(finalResult);
代码说明
- 初始化空对象
timeMap,用于存储每个time对应的所有日期结果 - 遍历原始数据中的每个日期项,再遍历该日期下的所有运行记录
- 将每个run的time转为数字作为键,为对应对象添加
time字段和各日期的结果值 - 最后用
Object.values()提取映射对象的所有值,转换为目标格式的数组
内容的提问来源于stack exchange,提问作者jaybee
相关产品推荐
相关产品推荐

