如何使用LINQ按星期几计算各仪表的平均值?
问题描述
我刚接触C#,首次使用LINQ查询。现有一个类型为Dictionary<(int MeterId, DateTime TimeStamp), float>的字典,数据示例如下:
<(10411, 12/1/2022 12:30:00 AM), 5700> <(10411, 13/1/2022 12:30:00 AM), 5200> <(10412, 12/1/2022 12:30:00 AM), 200>
需要编写方法将每个仪表的每周各天平均值存入列表,已写出部分LINQ代码,但不确定如何为AveragedMeter类的各星期平均值属性赋值。
AveragedMeter类定义:
class AveragedMeter { public int MeterId { get; set; } public float AverageMondayValue { get; set; } public float AverageTuesdayValue { get; set; } public float AverageWednesdayValue { get; set; } public float AverageThursdayValue { get; set; } public float AverageFridayValue { get; set; } public float AverageSaturdayValue { get; set; } public float AverageSundayValue { get; set; } }
现有方法代码:
public static List<AveragedMeter> CalculateAverageValues(Dictionary<(int MeterId, DateTime TimeStamp), float> groupedMeterValues) { var lstResult = groupedMeterValues .GroupBy(m => new { m.Key.MeterId, m.Key.TimeStamp.DayOfWeek }) .Select(g => new AveragedMeter { MeterId = g.Key.MeterId, AverageMondayValue, AverageTuesdayValue, AverageWednesdayValue, AverageThursdayValue, AverageFridayValue, AverageSaturdayValue, AverageSundayValue }) .ToList(); return lstResult; }
解决方案
你当前的分组逻辑有误——按仪表ID+星期几分组会得到每个仪表每天的独立分组,无法直接映射到AveragedMeter的7个属性。正确思路是先按MeterId分组,再在每个仪表组内计算各星期几的平均值,最后赋值到对应属性。
完整实现代码如下:
public static List<AveragedMeter> CalculateAverageValues(Dictionary<(int MeterId, DateTime TimeStamp), float> groupedMeterValues) { return groupedMeterValues // 第一步:按仪表ID分组,将同一仪表的所有数据归为一组 .GroupBy(m => m.Key.MeterId) .Select(meterGroup => new AveragedMeter { MeterId = meterGroup.Key, // 筛选周一数据并计算平均值,无数据时返回0 AverageMondayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Monday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle(), // 同理处理周二到周日 AverageTuesdayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Tuesday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle(), AverageWednesdayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Wednesday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle(), AverageThursdayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Thursday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle(), AverageFridayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Friday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle(), AverageSaturdayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Saturday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle(), AverageSundayValue = meterGroup .Where(item => item.Key.TimeStamp.DayOfWeek == DayOfWeek.Sunday) .Select(item => item.Value) .DefaultIfEmpty(0) .Average() .ToSingle() }) .ToList(); }
关键说明:
- 分组调整:先按
MeterId分组,确保每个组包含同一仪表的所有时间点数据。 - 平均值处理:
- 用
Where筛选对应星期的数据项 DefaultIfEmpty(0)避免空序列导致Average()抛出异常Average()返回double类型,通过ToSingle()转换为float匹配属性类型
- 用
- 属性赋值:直接将对应星期的平均值赋值到
AveragedMeter的对应属性中。
内容的提问来源于stack exchange,提问作者HARINDA VITHANA
相关产品推荐
相关产品推荐

