JavaScript中按时间累加两个有序对象数组值的高效实现方案
解决两个时序数组的缺失日期累加问题
这问题确实很典型——两个按时间排序的数组,要处理日期不匹配时用最近值补全求和,你最初的思路方向是对的,但只覆盖了"长数组有、短数组无"的情况,没考虑反过来的场景。其实利用两个数组已排序的特性,用双指针法就能在一次遍历里搞定所有情况,时间复杂度是O(n+m),非常高效。
核心思路
既然两个数组都是按日期升序排列的,我们可以用两个指针分别跟踪两个数组的当前位置,同时记录各自的"最近已知值"。每次比较两个指针指向的日期,优先处理更早的那个日期:
- 如果A数组的日期更早:用B数组的最近值和A的当前值相加,加入结果,然后移动A的指针,更新A的最近值。
- 如果B数组的日期更早:用A数组的最近值和B的当前值相加,加入结果,然后移动B的指针,更新B的最近值。
- 如果日期相同:直接相加两个值,加入结果,同时移动两个指针,更新各自的最近值。
- 当其中一个数组遍历完后,处理另一个数组剩下的元素,用对应的最近值补全求和。
代码实现
function mergeAndSum(data1, data2) { let i = 0, j = 0; const result = []; // 初始化最近值,处理数组为空的边界情况(如果数组为空,最近值设为0) let lastVal1 = data1.length > 0 ? data1[0].value : 0; let lastVal2 = data2.length > 0 ? data2[0].value : 0; // 辅助函数:将日期字符串转为Date对象,方便比较 const parseDate = (dateStr) => { const [day, month, year] = dateStr.split('-'); return new Date(year, month - 1, day); // 注意月份是0-based }; while (i < data1.length || j < data2.length) { // 获取当前指针的日期(如果指针越界,设为极大值,确保不会被优先处理) const date1 = i < data1.length ? parseDate(data1[i].date) : new Date(Infinity); const date2 = j < data2.length ? parseDate(data2[j].date) : new Date(Infinity); if (date1 < date2) { // data1的日期更早,用data2的最近值相加 result.push({ date: data1[i].date, value: data1[i].value + lastVal2 }); lastVal1 = data1[i].value; // 更新data1的最近值 i++; } else if (date2 < date1) { // data2的日期更早,用data1的最近值相加 result.push({ date: data2[j].date, value: data2[j].value + lastVal1 }); lastVal2 = data2[j].value; // 更新data2的最近值 j++; } else { // 日期相同,直接相加 result.push({ date: data1[i].date, value: data1[i].value + data2[j].value }); lastVal1 = data1[i].value; lastVal2 = data2[j].value; i++; j++; } } return result; } // 测试你的示例数据 const data1 = [ {date: "30-08-2019", value: 1}, {date: "03-09-2019", value: 2}, {date: "04-09-2019", value: 3} ]; const data2 = [ {date: "30-08-2019", value: 1}, {date: "02-09-2019", value: 2}, {date: "03-09-2019", value: 3}, {date: "04-09-2019", value: 4} ]; console.log(mergeAndSum(data1, data2)); // 输出结果和你期望的完全一致: // [ // { date: '30-08-2019', value: 2 }, // { date: '02-09-2019', value: 3 }, // { date: '03-09-2019', value: 5 }, // { date: '04-09-2019', value: 7 } // ]
为什么这个方案更好?
- 全覆盖:不管哪个数组有额外的日期,都能被正确处理,不会遗漏任何元素。
- 高效:只需要一次遍历两个数组,时间复杂度O(n+m),比先补全数组再求和的方法高效得多。
- 鲁棒性:处理了数组为空的边界情况,避免报错。
内容的提问来源于stack exchange,提问作者hanuruh
相关产品推荐
相关产品推荐

