2017-12-18 133 views
2

我的原始數據是這樣的:嵌套的字典:按日期組,然後按組枚舉值和彙總計數

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(); 

我在做什麼錯?

打印部(series1Series類派生):

foreach (var item in openData) 
{ 
     series1.Points.Add(new DataPoint() 
     { 
      YValues = new double[] { item.total }, 
      AxisLabel = item.dt.ToString(), 
      ToolTip = item.total.ToString() 
     }); 
} 

回答

1

您正在過濾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(); 
+0

嘿,感謝您的回答,請參閱約佔總數的總和我的編輯 –

1

有時候,一個簡單的嵌套foreach仍然可以得到最好的&清晰的解決方案。在大多數情況下,大數據集會比LINQ解決方案更快。

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); 
     } 
    } 
} 
1

在您的查詢的第一部分,你正在服用的集合中唯一的第一個項目。那麼你正在分組哪些是錯誤的。 嘗試如下:

 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(); 
1

我用下面的代碼來實現您所期望的:

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(); 

C# Fiddle Demo