如何使用 Linq 按日期时间和平均结果对字典进行分组
Posted
技术标签:
【中文标题】如何使用 Linq 按日期时间和平均结果对字典进行分组【英文标题】:How to group a Dictionary by DateTime and average results using Linq 【发布时间】:2021-02-11 20:18:23 【问题描述】:我有这个数据集。
var results = new Dictionary<DateTime, Result>()
Result
类如下所示:
public class Result
public decimal Temperature get; set
public decimal DayTime get; set;
我的数据集将如下所示:
Dictionary Key Dictionary Value (Result class)
-------------- -------------------------------
01/01/2020 09:00 Temperature: +9, DayTime: true
01/01/2020 18:00 Temperature: +5, DayTime: false
01/02/2020 09:00 Temperature: +8, DayTime: true
01/02/2020 18:00 Temperature: +3, DayTime: false
我的目标是平均每月的昼夜温度,这将给出如下结果:
01/2020 - DayTime Avg. Temp +9
01/2020 - NightTime Avg. Temp +5
02/2020 - DayTime Avg. Temp +8
02/2020 - NightTime Avg. Temp + 3
请注意,会有更多数据点,因为我将拥有给定年份每天每一小时的数据。
我已经开始在 Dictionary
类型上使用 GroupBy()
方法,但我不知道如何深入每个结果以按日/夜分开并平均温度。
这可能与 Linq 相关,还是我应该只循环结果,使用 linq 提取月度数据并取平均值?我可以得到一个不同的月份列表,然后循环选择日/夜值并执行平均值?
如果有更简洁的方法可以做到这一点,我很乐意学习。
【问题讨论】:
你试过OrderBy
的方法吗?
@RamonDias : OrderBy 如何解决平均问题?
Result
的DayTime
属性不应该是bool
吗?
【参考方案1】:
您只需要嵌套GroupBy
s 来处理每个分组:一个用于日期,一个用于DayTime
。我使用SelectMany
来展平子分组,但您可以保留它们。
var ans = results.GroupBy(dr => dr.Key.Date, dr => dr.Value)
.SelectMany(rg => rg.GroupBy(r => r.DayTime, r => r.Temperature).Select(tg => new Date = rg.Key, DayTime = tg.Key, AvgTemp = tg.Average() ))
.ToList();
【讨论】:
【参考方案2】:在一个 linq 中完成这项工作具有挑战性。您需要两个不均匀的 9 小时和 15 小时分组。因此,您按天分组,然后减去 9 小时以开始上午 9:00,然后测试偏移量是否小于 9 小时(上午 9:00 到下午 6:00)或更大。我不得不让温度接受一个空值,因为一个范围可能没有温度。 请参阅下面的解决方案
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
class Program
static void Main(string[] args)
TimeSpan SIX_PM = new TimeSpan(18, 0, 0); // Time from midnight to 6PM;
List<Result> input = new List<Result>()
new Result() DayTime = DateTime.Parse("10/28/20 2:00"), Temperature = 2,
new Result() DayTime = DateTime.Parse("10/28/20 4:00"), Temperature = 3,
new Result() DayTime = DateTime.Parse("10/28/20 6:00"), Temperature = 4,
new Result() DayTime = DateTime.Parse("10/28/20 8:00"), Temperature = 5,
new Result() DayTime = DateTime.Parse("10/28/20 10:00"), Temperature = 6,
new Result() DayTime = DateTime.Parse("10/28/20 12:00"), Temperature = 7,
new Result() DayTime = DateTime.Parse("10/28/20 14:00"), Temperature = 8,
new Result() DayTime = DateTime.Parse("10/28/20 16:00"), Temperature = 9,
new Result() DayTime = DateTime.Parse("10/28/20 18:00"), Temperature = 10,
new Result() DayTime = DateTime.Parse("10/28/20 20:00"), Temperature = 11,
new Result() DayTime = DateTime.Parse("10/28/20 22:00"), Temperature = 12,
new Result() DayTime = DateTime.Parse("10/29/20 0:00"), Temperature = 13,
new Result() DayTime = DateTime.Parse("10/29/20 2:00"), Temperature = 14,
new Result() DayTime = DateTime.Parse("10/29/20 4:00"), Temperature = 15,
new Result() DayTime = DateTime.Parse("10/29/20 6:00"), Temperature = 16,
new Result() DayTime = DateTime.Parse("10/29/20 8:00"), Temperature = 17,
new Result() DayTime = DateTime.Parse("10/29/20 10:00"), Temperature = 18,
new Result() DayTime = DateTime.Parse("10/29/20 12:00"), Temperature = 19,
new Result() DayTime = DateTime.Parse("10/29/20 14:00"), Temperature = 20,
new Result() DayTime = DateTime.Parse("10/29/20 16:00"), Temperature = 21,
new Result() DayTime = DateTime.Parse("10/29/20 18:00"), Temperature = 22,
new Result() DayTime = DateTime.Parse("10/29/20 20:00"), Temperature = 23,
new Result() DayTime = DateTime.Parse("10/29/20 22:00"), Temperature = 24
;
Dictionary<DateTime, Result> results = input.GroupBy(x => x.DayTime, y => y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
var data = results.GroupBy(x => x.Key.AddHours(-9).Date)
.SelectMany(x => Enumerable.Range(0, 2)
.Select(y => (y == 0)
? new
Date = x.Key.AddHours(9).ToString(),
AverageTemperature = x.Where(z => z.Key - x.Key < SIX_PM)
.Average(z => z.Value.Temperature),
DayTime = "DayTime"
: new
Date = x.Key.AddHours(18).ToString(),
AverageTemperature = x.Where(z => z.Key - x.Key >= SIX_PM)
.Average(z => z.Value.Temperature),
DayTime = "NightTime"
))
.Where(x => x.AverageTemperature != null)
.ToList();
public class Result
public decimal? Temperature get; set;
public DateTime DayTime get; set;
【讨论】:
以上是关于如何使用 Linq 按日期时间和平均结果对字典进行分组的主要内容,如果未能解决你的问题,请参考以下文章