
本文介绍如何在 JavaScript 中对多个长度不一、但共享时间戳的时间序列数组进行高效聚合,按统一时间点对所有可用数值求平均,并输出标准 [timestamp, avgValue] 格式结果,全程无需依赖 Lodash 等外部库。
本文介绍如何在 javascript 中对多个长度不一、但共享时间戳的时间序列数组进行高效聚合,按统一时间点对所有可用数值求平均,并输出标准 `[timestamp, avgvalue]` 格式结果,全程无需依赖 lodash 等外部库。
在时序数据分析场景中(如传感器数据融合、多源指标对齐),常遇到多个时间序列数组长度不同——这是因部分时间点数据缺失所致。核心需求是:以时间戳为键,聚合所有数组中该时刻的有效观测值,并计算算术平均值。关键在于避免循环嵌套与重复遍历,兼顾可读性与性能。
以下是一个简洁、现代、无依赖的实现方案:
const array1 = [[1, 100], [2, 200], [3, 300], [4, 400]];
const array2 = [[1, 150], [3, 350], [4, 450]];
const array3 = [[1, 250], [2, 350], [4, 450]];
const allArrays = [array1, array2, array3];
// 步骤 1:扁平化 + 按时间戳分组(使用 reduce + nullish coalescing assignment)
const groupedByTime = allArrays
.flat() // 替代 [...array1, ...array2, ...array3],更简洁且支持任意数量数组
.reduce((acc, [time, value]) => {
(acc[time] ??= []).push(value);
return acc;
}, {});
// 步骤 2:转换为最终格式:[timestamp, avgValue.toFixed(1)]
const averagedResult = Object.entries(groupedByTime)
.map(([timeStr, values]) => {
const avg = values.reduce((sum, v) => sum + v, 0) / values.length;
return [Number(timeStr), parseFloat(avg.toFixed(1))]; // toFixed 返回字符串,parseFloat 转回数字更稳妥
})
.sort((a, b) => a[0] - b[0]); // 可选:确保按时间升序排列
console.log(averagedResult);
// 输出:[[1, 166.7], [2, 275], [3, 325], [4, 433.3]]✅ 关键设计说明:
- Array.prototype.flat() 替代手动展开,天然支持任意数量输入数组,语义清晰;
- ??=(空值合并赋值)确保首次访问某时间戳时自动初始化为空数组,避免 undefined.push() 错误;
- Object.entries() 将分组对象转为 [key, value] 数组,便于映射处理;
- parseFloat(avg.toFixed(1)) 在保留一位小数的同时维持数值类型(而非字符串),利于后续计算或序列化;
- 最后 .sort() 保证输出严格按时间戳升序,符合时间序列惯例(原始输入时间戳已有序,但健壮性建议显式排序)。
⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 时间戳应为合法数字(如 Unix 秒/毫秒)。若含字符串时间(如 "2024-01-01"),需先统一解析为数字(例如用 Date.parse() 或 new Date().getTime());
- 若存在极端稀疏数据(如某时间戳仅一个值),平均逻辑仍正确;若完全无数据,则该时间戳不会出现在结果中;
- 对于超大规模数据(>10⁵ 点),可考虑使用 Map 替代普通对象提升键查找性能(Map 对数字/字符串键均有优化);
- 如需加权平均、中位数或忽略异常值,可在 values 数组上扩展预处理逻辑(如 values.filter(isValid))。
该方法兼具函数式编程的表达力与生产环境所需的健壮性,是处理异构时间序列对齐任务的推荐实践。










