如何用Reduce合并API返回的同日期时间数据?
按日期合并预约时间数组解决方案
原始API数据
[ { "startDate": "2023-03-05T08:00:00", }, { "startDate": "2023-03-05T08:15:00", }, { "startDate": "2023-03-05T08:30:00", }, { "startDate": "2023-03-06T11:30:00", }, { "startDate": "2023-03-06T12:00:00", }, ]
期望输出结构
[ { startDate: "2023-03-05", time: [{timeSlotId: 8200, formattedTime: '08:00'}, {timeSlotId: 8201, formattedTime: '08:15'}, {timeSlotId: 8202, formattedTime: '08:30'}], }, { startDate: "2023-03-06", time: [{timeSlotId: 8300, formattedTime: '11:30'}, {timeSlotId: 8301, formattedTime: '12:00'} ], }, ]
问题代码分析
你当前的reduce用法存在几个核心问题:
- 未指定
reduce的初始累积值(第二个参数),导致第一次迭代时acc是数组的第一个元素,而非我们需要的空数组容器 - 错误地将
acc当作单个对象处理,实际acc应该是存储分组对象的数组 - 每次迭代都直接返回新数组覆盖累积结果,完全丢失了之前的分组数据
- 未处理
timeSlotId的生成逻辑,且formattedTime的赋值逻辑不完整
修正后的代码
// 假设已引入moment库 const formattedAppointments = (dataAppointments?.slice(0, 10) || []).reduce((acc, appointment) => { const dateStr = moment(appointment.startDate).format('YYYY-MM-DD'); const formattedTime = moment(appointment.startDate).format('HH:mm'); // 查找当前日期是否已存在分组 const existingGroup = acc.find(group => group.startDate === dateStr); if (existingGroup) { // 生成timeSlotId:同一日期内按顺序递增,前缀按分组索引设置(82、83...) const groupIndex = acc.indexOf(existingGroup); const timeSlotId = (82 + groupIndex) * 100 + existingGroup.time.length; existingGroup.time.push({ timeSlotId, formattedTime }); } else { // 新日期分组,timeSlotId从8200、8300...开始 const groupIndex = acc.length; const timeSlotId = (82 + groupIndex) * 100; acc.push({ startDate: dateStr, time: [{ timeSlotId, formattedTime }] }); } return acc; }, []); // 这里必须传入初始空数组作为acc的初始值 console.log(formattedAppointments);
代码说明
- 初始值设置:给
reduce传入空数组[]作为初始累积值,确保acc始终是存储分组对象的数组 - 日期分组逻辑:每次迭代先提取当前预约的日期字符串,检查
acc中是否已有该日期的分组 - timeSlotId生成:按照示例中的规则,第一个日期分组前缀为82,第二个为83,每个分组内的时间项按顺序递增后缀(00、01...)
- 累积更新:已有分组则追加时间项,无分组则新增分组对象,始终返回累积数组
acc
内容的提问来源于stack exchange,提问作者wasilikoslow
相关产品推荐
相关产品推荐

