C#多集合合并求助:将多传感器数据合并为带补0的时间序列
合并多传感器MeasuredData集合的实现方案
嘿,这个合并传感器数据的需求我之前做项目时刚好碰到过,核心就是要把所有时间点都覆盖到,缺数据的补0对吧?我给你梳理一个清晰的实现方案,分步骤来:
核心思路
- 收集全量时间点:把所有传感器的
MeasuredData里的Time都提取出来,去重后按时间排序,确保每个时间点都不会遗漏。 - 逐个时间点匹配数据:对每个时间点,检查每个传感器的数据集里是否存在对应数据,有就取
Value,没有就填0。 - 用实体类规整合并结果(可选但推荐):定义一个专门的类来存储每个时间点的所有传感器数据,方便后续输出或处理。
代码实现
第一步:定义合并结果实体类
我们用字典来存储每个传感器的数值,键是传感器名称,值是对应时间的数值(0表示无数据):
public class MergedMeasuredData { public DateTime Time { get; set; } public Dictionary<string, double> SensorValues { get; set; } = new Dictionary<string, double>(); }
第二步:基础合并方法
这个版本逻辑直观,适合数据量不大的场景:
public static List<MergedMeasuredData> MergeSensorData(Dictionary<string, List<MeasuredData>> sensorDataMap) { // 收集所有唯一时间点并排序 var allTimePoints = sensorDataMap.Values .SelectMany(data => data.Select(d => d.Time)) .Distinct() .OrderBy(time => time) .ToList(); var mergedData = new List<MergedMeasuredData>(); foreach (var timePoint in allTimePoints) { var mergedEntry = new MergedMeasuredData { Time = timePoint }; foreach (var sensorEntry in sensorDataMap) { string sensorName = sensorEntry.Key; List<MeasuredData> sensorData = sensorEntry.Value; // 查找当前传感器在该时间点的数据,没有就填0 var dataPoint = sensorData.FirstOrDefault(d => d.Time == timePoint); mergedEntry.SensorValues[sensorName] = dataPoint?.Value ?? 0; } mergedData.Add(mergedEntry); } return mergedData; }
第三步:性能优化版本
如果你的传感器数据量很大,每次用FirstOrDefault遍历查找会比较慢,我们可以提前把每个传感器的数据转成Dictionary<DateTime, double>,这样查找时间从O(n)降到O(1):
public static List<MergedMeasuredData> MergeSensorDataOptimized(Dictionary<string, List<MeasuredData>> sensorDataMap) { // 提前将每个传感器的数据转为DateTime到Value的字典,提升查找性能 var sensorDataDictMap = sensorDataMap.ToDictionary( k => k.Key, v => v.Value.ToDictionary(d => d.Time, d => d.Value) ); var allTimePoints = sensorDataDictMap.Values .SelectMany(dict => dict.Keys) .Distinct() .OrderBy(time => time) .ToList(); var mergedData = new List<MergedMeasuredData>(); foreach (var timePoint in allTimePoints) { var mergedEntry = new MergedMeasuredData { Time = timePoint }; foreach (var sensorEntry in sensorDataDictMap) { string sensorName = sensorEntry.Key; var sensorDataDict = sensorEntry.Value; // 尝试获取数据,不存在则返回0 mergedEntry.SensorValues[sensorName] = sensorDataDict.TryGetValue(timePoint, out double value) ? value : 0; } mergedData.Add(mergedEntry); } return mergedData; }
示例用法
这里模拟两个传感器的数据,看看合并后的效果:
// 模拟传感器1的数据(温度) var sensorTempData = new List<MeasuredData> { new MeasuredData(new DateTime(2024, 5, 20, 10, 0, 0), 25.5), new MeasuredData(new DateTime(2024, 5, 20, 10, 1, 0), 26.1) }; // 模拟传感器2的数据(湿度) var sensorHumidityData = new List<MeasuredData> { new MeasuredData(new DateTime(2024, 5, 20, 10, 0, 0), 60.2), new MeasuredData(new DateTime(2024, 5, 20, 10, 2, 0), 61.0) }; // 把传感器数据按名称存入字典 var sensorDataMap = new Dictionary<string, List<MeasuredData>> { { "Sensor_Temperature", sensorTempData }, { "Sensor_Humidity", sensorHumidityData } }; // 调用合并方法 var mergedResult = MergeSensorDataOptimized(sensorDataMap); // 输出合并结果 foreach (var entry in mergedResult) { Console.WriteLine($"时间: {entry.Time:yyyy-MM-dd HH:mm:ss}"); foreach (var sensorValue in entry.SensorValues) { Console.WriteLine($" {sensorValue.Key}: {sensorValue.Value}"); } }
运行后输出的结果会是:
时间: 2024-05-20 10:00:00 Sensor_Temperature: 25.5 Sensor_Humidity: 60.2 时间: 2024-05-20 10:01:00 Sensor_Temperature: 26.1 Sensor_Humidity: 0 时间: 2024-05-20 10:02:00 Sensor_Temperature: 0 Sensor_Humidity: 61.0
这样就完美满足你的需求啦,每个时间点都包含所有传感器的数据,缺的自动补0。
内容的提问来源于stack exchange,提问作者coding
相关产品推荐
相关产品推荐

