嵌套字典:按日期分组,然后按枚举值分组并汇总计数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌套字典:按日期分组,然后按枚举值分组并汇总计数相关的知识,希望对你有一定的参考价值。
我的原始数据如下所示:
IDictionary<DateTime, IDictionary<ReportType, int>> rawData
例:
19/09/2017, [(ReportType.Open, 2)]
25/09/2017, [(ReportType.Open, 15), (ReportType.Sent, 15)]
25/10/2017, [(ReportType.Open, 27), (ReportType.Sent, 15)]
29/10/2017, [(ReportType.Sent, 150)]
我正在尝试实现以下结果:
data for open:
september-2017: 17
october-2017: 27
data for sent:
september-2017: 15
october-2017: 165
-----------------------------
我试过了
var openData = rawData
.Select(g => new {
dt = string.Format("{0}/{1}", g.Key.Month, g.Key.Year),
g.Key.Year,
g.Key.Month,
action = g.Value.FirstOrDefault().Key,
total = g.Value.Values.Sum()
})
.GroupBy(l => new {
l.Month,
l.Year,
action = l.action
})
.Where(a => a.Key.action == ReportType.Open)
.OrderByDescending(a => a.Key)
.ToList();
我究竟做错了什么?
打印部分(series1
源自Series
类):
foreach (var item in openData)
{
series1.Points.Add(new DataPoint()
{
YValues = new double[] { item.total },
AxisLabel = item.dt.ToString(),
ToolTip = item.total.ToString()
});
}
你正在过滤Open reporttype
错误的地方;
var openData = rawData
.Select(g => new {
dt = string.Format("{0}/{1}", g.Key.Month, g.Key.Year),
g.Key.Year,
g.Key.Month,
actions = g.Value.Where(x => x.Key == ReportType.Open) //Filter it here
})
.GroupBy(l => new {
l.Month,
l.Year
})
.Select(s =>
new
{
s.Key.Month,
s.Key.Year,
s.Sum(x => x.actions.Sum(sum => sum.Value))
})
.ToList();
有时一个简单的嵌套qazxsw poi仍然是最好和最清晰的解决方案。在大多数情况下,它将使用大型数据集,比LINQ解决方案更快。
foreach
在查询的第一部分中,您只获取集合中的第一个项目。然后你分组哪个是错的。试试以下:
Dictionary<string, int> openCounts = new Dictionary<string, int>();
Dictionary<string, int> sentCounts = new Dictionary<string, int>();
foreach (var kvp in rawData)
{
//var dt = string.Format("{0}-{1}", kvp.Key.ToString("MMMM"), kvp.Key.Year);
var dt = kvp.Key.ToString("MMMM-yyyy"); //simpler alternative, "MMMM" gives full month name
foreach (var val in kvp.Value)
{
if (val.Key == ReportType.Open)
{
if (openCounts.ContainsKey(dt))
openCounts[dt] += val.Value;
else
openCounts.Add(dt, val.Value);
}
else
{
if (sentCounts.ContainsKey(dt))
sentCounts[dt] += val.Value;
else
sentCounts.Add(dt, val.Value);
}
}
}
我使用下面的代码来实现你的期望:
var ob = (from m in rawData
where m.Value.Keys.Any(i => i != ReportType.Sent)
group m by new { m.Key.Year, m.Key.Month, m.Value.Keys } into gx
select new
{
Date = new DateTime(gx.Key.Year, gx.Key.Month, 1),
// taa = gx.Key.Keys,
Total = gx.Select(m => m.Value.Values).ToList().Select(y => y.Sum()).FirstOrDefault()
}).ToList();
var result = rawData
.SelectMany(c => c.Value, (b, c) => new { b.Key.Year, Month = b.Key.ToString("MMMM"), c.Key, c.Value })
// At first I unwind nested data
.GroupBy(g => g.Key)
// Then create my new group by ReportType
.Select(c => new {
c.Key,
Data = c.GroupBy(g => new { g.Year, g.Month })
.Select(f => new { f.Key.Year, f.Key.Month, Sum = f.Sum(s => s.Value) })
// Each ReportType has many groups of monthes of each year
})
// At last create my custom type
.ToList();
以上是关于嵌套字典:按日期分组,然后按枚举值分组并汇总计数的主要内容,如果未能解决你的问题,请参考以下文章