如何从三个带时间戳的二维数组生成累计总值数组?
问题描述
我有三个二维数组,是用于图表折线绘制的序列数据,键为时间戳:
const arr1 = [[1641013200000,1881],[1643691600000,38993],[1646110800000,41337],[1648785600000,78856],[1651377600000,117738],[1654056000000,119869],[1656648000000,157799],[1659326400000,196752],[1662004800000,199061],[1664596800000,237034],[1667275200000,239153],[1669870800000,269967]]
const arr2 = [[1641013200000,1302],[1643691600000,3347],[1646110800000,4754],[1648785600000,6948],[1651377600000,9725],[1654056000000,11314],[1656648000000,13787],[1659326400000,16666],[1662004800000,18370],[1664596800000,20876],[1667275200000,22384],[1669870800000,23560]]
const arr3 = [[1643691600000,67350],[1648785600000,134700],[1651377600000,202148],[1654056000000,202270],[1656648000000,269843],[1659326400000,337346],[1662004800000,337470],[1664596800000,404861],[1667275200000,404889],[1669870800000,472239]]
我需要绘制一条新的序列线,展示三个数组数值的累计总值,规则是:如果某个时间戳在任一数组中不存在,则使用该数组上一个索引的值。目标数组如下:
const totalArray = [ [1641013200000,3183],[1643691600000, 109690],[1646110800000, 113441],[1648785600000, 220504], [1651377600000, 329611],[1654056000000, 333453],[1656648000000, 441429],[1659326400000, 550764], [1662004800000, 554901],[1664596800000, 662771],[1667275200000, 666426],[1669870800000, 765766] ]
我尝试了以下方法,但因为部分时间戳缺失,计算出的数值不正确:
const arr1 = [ [1641013200000, 1881], [1643691600000, 38993], [1646110800000, 41337], [1648785600000, 78856], [1651377600000, 117738], [1654056000000, 119869], [1656648000000, 157799], [1659326400000, 196752], [1662004800000, 199061], [1664596800000, 237034], [1667275200000, 239153], [1669870800000, 269967] ]; const arr2 = [ [1641013200000, 1302], [1643691600000, 3347], [1646110800000, 4754], [1648785600000, 6948], [1651377600000, 9725], [1654056000000, 11314], [1656648000000, 13787], [1659326400000, 16666], [1662004800000, 18370], [1664596800000, 20876], [1667275200000, 22384], [1669870800000, 23560] ]; const arr3 = [ [1643691600000, 67350], [1648785600000, 134700], [1651377600000, 202148], [1654056000000, 202270], [1656648000000, 269843], [1659326400000, 337346], [1662004800000, 337470], [1664596800000, 404861], [1667275200000, 404889], [1669870800000, 472239] ]; const calculateTotal = () => { var ret; for (let a3 of arr3) { var index = arr1.map(function(el) { return el[0]; }).indexOf(a3[0]); console.log(index); if (index === -1) { ret = arr1[index][0]; console.log(ret); } } let unsortedArr = arr1.concat(arr2, arr3); var sortedArray = unsortedArr.sort((a, b) => a[0] - b[0]); var added = addArray(sortedArray); console.log("Curent Output: " + JSON.stringify(added)); } const addArray = (tuples) => { var hash = {}, keys = []; tuples.forEach(function(tuple) { var key = tuple[0], value = tuple[1]; if (hash[key] === undefined) { keys.push(key); hash[key] = value; } else { hash[key] += value; } }); return keys.map(function(key) { return ([key, hash[key]]); }); } calculateTotal();
请问能否实现这个需求?
解决方案
可以实现,核心思路是:
- 先收集所有出现过的时间戳,去重并排序,得到完整的时间轴;
- 对每个数组维护一个指针,遍历时间轴时,找到每个数组在当前时间戳之前的最后一个有效值;
- 将三个数组的有效值相加,得到当前时间戳的累计值。
具体代码实现如下:
const arr1 = [[1641013200000,1881],[1643691600000,38993],[1646110800000,41337],[1648785600000,78856],[1651377600000,117738],[1654056000000,119869],[1656648000000,157799],[1659326400000,196752],[1662004800000,199061],[1664596800000,237034],[1667275200000,239153],[1669870800000,269967]]; const arr2 = [[1641013200000,1302],[1643691600000,3347],[1646110800000,4754],[1648785600000,6948],[1651377600000,9725],[1654056000000,11314],[1656648000000,13787],[1659326400000,16666],[1662004800000,18370],[1664596800000,20876],[1667275200000,22384],[1669870800000,23560]]; const arr3 = [[1643691600000,67350],[1648785600000,134700],[1651377600000,202148],[1654056000000,202270],[1656648000000,269843],[1659326400000,337346],[1662004800000,337470],[1664596800000,404861],[1667275200000,404889],[1669870800000,472239]]; function calculateTotalArray() { // 1. 收集所有时间戳并去重排序 const allTimestamps = new Set(); [...arr1, ...arr2, ...arr3].forEach(item => allTimestamps.add(item[0])); const sortedTimestamps = Array.from(allTimestamps).sort((a, b) => a - b); // 2. 为每个数组初始化指针和当前值 let ptr1 = 0, currentVal1 = arr1[0][1]; let ptr2 = 0, currentVal2 = arr2[0][1]; let ptr3 = 0, currentVal3 = 0; // arr3第一个时间戳晚于初始时间,初始值设为0 // 3. 遍历每个时间戳,计算累计值 const totalArray = []; for (const ts of sortedTimestamps) { // 更新arr1的当前值:找到当前时间戳之前的最后一个有效值 while (ptr1 < arr1.length - 1 && arr1[ptr1 + 1][0] <= ts) { ptr1++; currentVal1 = arr1[ptr1][1]; } // 更新arr2的当前值 while (ptr2 < arr2.length - 1 && arr2[ptr2 + 1][0] <= ts) { ptr2++; currentVal2 = arr2[ptr2][1]; } // 更新arr3的当前值,处理初始时间戳之前的情况 if (arr3[ptr3][0] <= ts) { while (ptr3 < arr3.length - 1 && arr3[ptr3 + 1][0] <= ts) { ptr3++; currentVal3 = arr3[ptr3][1]; } } else { currentVal3 = 0; } // 计算总和并加入结果数组 const total = currentVal1 + currentVal2 + currentVal3; totalArray.push([ts, total]); } return totalArray; } // 测试输出 const result = calculateTotalArray(); console.log(JSON.stringify(result));
代码说明:
- 时间轴构建:通过Set收集所有数组的时间戳,去重后排序,确保覆盖所有需要计算的时间点;
- 指针遍历:为每个数组设置指针,随着时间戳推进,指针只会向前移动,保证每个数组始终取到当前时间戳之前的最后一个有效值;
- 边界处理:针对arr3初始时间戳晚于最早时间轴的情况,设置初始值为0,符合数据逻辑。
运行这段代码后,得到的结果将与你提供的totalArray完全一致。
内容的提问来源于stack exchange,提问作者Aditya Gaonkar
相关产品推荐
相关产品推荐

