我有一个列表,我需要通过创建来计算每天的平均价值。我如何优雅地迭代列表中列出的每一天的列表?每天可能会有间隔,每天的对象数量会有所不同。
例如,值可能是这样的:
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的简单方法
答案 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);
}