如何在TypeScript中转换/扁平化包含数组的对象数组?
TypeScript 实现时间序列数据结构转换
需求说明
原始数据按「图层(layer)」分组,每个图层下包含多条带时间戳的数值记录;需要将其转换为按「时间戳(timestamp)」聚合的结构,每个时间戳条目包含所有图层对应的数值。
原始数据结构:
{"layers": [{"layer": "foo","values": [{"timestamp": "1970-01-01T00:00:00Z","value": 0},{"timestamp": "1970-01-01T01:00:00Z","value": 0},{"timestamp": "1970-01-01T02:00:00Z","value": 0},{"timestamp": "1970-01-01T03:00:00Z","value": 0}]},{"layer": "bar","values": [{"timestamp": "1970-01-01T00:00:00Z","value": 1},{"timestamp": "1970-01-01T01:00:00Z","value": 1},{"timestamp": "1970-01-01T02:00:00Z","value": 1},{"timestamp": "1970-01-01T03:00:00Z","value": 1}]}]}
目标数据结构:
[{"timestamp": "1970-01-01T00:00:00Z","foo": 0,"bar": 1},{"timestamp": "1970-01-01T01:00:00Z","foo": 0,"bar": 1},{"timestamp": "1970-01-01T02:00:00Z","foo": 0,"bar": 1},{"timestamp": "1970-01-01T03:00:00Z","foo": 0,"bar": 1}]
实现方案
1. 定义类型(TypeScript 类型约束)
先为原始数据和目标数据定义接口,确保类型安全:
// 原始数据的单条数值记录 interface RawValue { timestamp: string; value: number; } // 原始数据的图层结构 interface RawLayer { layer: string; values: RawValue[]; } // 原始数据整体结构 interface RawData { layers: RawLayer[]; } // 转换后的单条记录类型(动态键对应图层名称) type TransformedRecord = { timestamp: string; } & Record<string, number>;
2. 转换函数实现
核心思路是用 Map 按时间戳聚合所有图层的数值,最后将 Map 转换为数组:
function transformData(rawData: RawData): TransformedRecord[] { // 用 Map 存储每个时间戳对应的聚合结果 const timestampMap = new Map<string, TransformedRecord>(); // 遍历每个图层 rawData.layers.forEach(({ layer, values }) => { // 遍历当前图层的所有数值记录 values.forEach(({ timestamp, value }) => { // 如果 Map 中已有该时间戳的条目,直接添加当前图层的键值对 if (timestampMap.has(timestamp)) { const existingRecord = timestampMap.get(timestamp)!; existingRecord[layer] = value; } else { // 没有则创建新条目,初始化时间戳和当前图层的数值 timestampMap.set(timestamp, { timestamp, [layer]: value }); } }); }); // 将 Map 的值转换为数组并返回 return Array.from(timestampMap.values()); }
3. 使用示例
// 原始数据示例 const inputData: RawData = { "layers": [ {"layer": "foo","values": [{"timestamp": "1970-01-01T00:00:00Z","value": 0},{"timestamp": "1970-01-01T01:00:00Z","value": 0},{"timestamp": "1970-01-01T02:00:00Z","value": 0},{"timestamp": "1970-01-01T03:00:00Z","value": 0}]}, {"layer": "bar","values": [{"timestamp": "1970-01-01T00:00:00Z","value": 1},{"timestamp": "1970-01-01T01:00:00Z","value": 1},{"timestamp": "1970-01-01T02:00:00Z","value": 1},{"timestamp": "1970-01-01T03:00:00Z","value": 1}]} ] }; // 执行转换 const outputData = transformData(inputData); console.log(outputData); // 输出结果与目标结构一致
关键说明
- 使用
Map可以高效按时间戳去重和聚合,避免重复遍历数组 - 动态属性
[layer]用于将图层名称作为对象的键,适配任意图层名称 - 类型定义确保了输入输出的类型安全,减少运行时错误
内容的提问来源于stack exchange,提问作者mrt181
相关产品推荐
相关产品推荐

