通过DateTime属性遍历列表

时间:2018-07-18 12:02:03

标签: c# .net

我有一个列表,我需要通过创建来计算每天的平均价值。我如何优雅地迭代列表中列出的每一天的列表?每天可能会有间隔,每天的对象数量会有所不同。

例如,值可能是这样的:

public class MyObject
{
    public double Value { get; set; }
    public DateTime Created { get; set; }
}

{ Value: 1, Created: 2018-07-01 12:00:00 }
{ Value: 4, Created: 2018-07-01 20:00:00 }
{ Value: 2, Created: 2018-07-03 12:00:00 }
{ Value: 3, Created: 2018-07-04 09:00:00 }
{ Value: 2, Created: 2018-07-04 11:00:00 }
{ Value: 6, Created: 2018-07-04 12:00:00 }
{ Value: 5, Created: 2018-07-06 16:00:00 }
{ Value: 3, Created: 2018-07-06 11:00:00 }

我可以去找这样的东西...

List<MyObject> items = itemsfrombackend;
DateTime beginDay = items.First().Created;
DateTime endDay = items.Last().Created;
for (DateTime day = beginDay; day <= endDay; day.AddDays(1))
{
    // if items contains any matching objects calculate avg
}

但是想找到一种更少的ifs的简单方法

3 个答案:

答案 0 :(得分:5)

我会结合使用GroupBy()Average()

var result = items.GroupBy(x => x.Created.Date)
                  .Select(x => new { Created = x.Key, Avg = x.Average(y => y.Value) });

答案 1 :(得分:3)

您可以使用LINQ来group the data并计算平均值。您可以使用DateTime.Date来检索DateTime值的日期部分,例如:

var averages=items.GroupBy(grp=>grp.Created.Date)
        .Select(grp=>new {Date=grp.Key,Average=grp.Average(it=>it.Value)});

或以查询形式:

var averages=from item in items
             group item by item.Created.Date into grp
             select new { Date=grp.Key,
                          Average=grp.Average(it=>it.Value)
                        };

GroupBy创建一个共享相同密钥的项目的“存储桶”。该存储桶可以视为一个集合,可让您对其进行过滤,选择单个项目或根据其内容计算聚合函数,例如Averabe()

Average()重载之一可以让您specify the property进行计算。

grp.Average(it=>it.Value)

选择并平均每个组的存储桶中Value个项目的内容

答案 2 :(得分:1)

您可以使用LINQ完全解决它,如其他人所述。您也可以尝试这种方法,它具有一些LINQ;-)

Dictionary<DateTime, decimal> avg = new Dictionary<DateTime, decimal>();

foreach (MyObject obj in items)
{
    if (avg.ContainsKey(obj.Created.Date))
    {
        avg[obj.Created.Date] += (decimal)obj.Value;
    }
    else
    {
        avg.Add(obj.Created.Date, (decimal)obj.Value);
    }
}

foreach (var item in avg.ToList())
{
    avg[item.Key] =Math.Round(item.Value / items.Count(x => x.Created.Date == Convert.ToDateTime(item.Key).Date),1);
}