表格中的聚合列表示为List <dictionary <column,value =“”>&gt; </dictionary <column,>

时间:2011-01-24 09:33:26

标签: c# .net linq aggregation

什么是在表格中聚合列值的LINQ方式,其中每一行都是Dictionary<ColumnT, ValueT>

数据表的格式为

   2010 | 2011
A    11 |   12
B    21 |   22

这表示为词典列表:

var A = new Dictionary<String, int>();
A.Add("2010", 11);
A.Add("2011"  12),
var B = new Dictionary<String, int>();
A.Add("2010", 21);
A.Add("2011"  22),
var table = List<Dictionary<String,int>>() { A, B };

如何生成汇总来自其他行的所有列的总计行?总计行也可以像其他行一样Dictionary<String, int>

旧式的方式是:

var totalsRow = new Dictionary<String, int>();
foreach(Dictionary<String, int> row in table)
{
    foreach(var cell in row)
    {
       // Get running sum (add if not present)
       int TValue= 0;
       if (!totalsRow.TryGetValue(cell.Key, out cellValue))
       {
          totalsRow.Add(cell.Key, 0);
       }

       // Increment using an aggregation function (e.g. sum)
       totalsRow[cell.Key] = AggregationFunc(totalsRow[cell.Key], cellValue);
    }
}

有没有更简洁的LINQ方式呢?

如果没有,那么定义扩展方法(在Dictionary上)以包装上述代码的最类似LINQ的方法是什么?

澄清AggregationFunc是获取正在运行的总计和下一个项目值并生成新的运行总计的任何函数,例如:

int Sum(int sum, int nextValue) { return sum + nextValue; }

2 个答案:

答案 0 :(得分:4)

我认为你的最后一行实际上是:

totalsRow[cell.Key] = AggregationFunc(runningValue, cell.Value);

因为否则,您没有在任何地方使用嵌入字典的整数值。


你可以这样做:

var totalsRow = table.SelectMany(row => row)
                     .GroupBy(kvp => kvp.Key)
                     .ToDictionary(group => group.Key, 
                                   group => group.Sum(kvp => kvp.Value));

如果要保留AggregationFunc,请将第二个参数替换为ToDictionary

group => group.Aggregate(0, 
         (runningValue, nextKvp) => AggregationFunc(runningValue, nextKvp.Value))

这个想法是:

  1. 首先将词典列表展平成为键值对的序列
  2. 按键对键值对进行分组。
  3. 将键值对的组转换为字典,其中包含:
    • “密钥”是的密钥,即组中所有对共享的密钥。
    • “值”是组中所有对的各个值的聚合。

答案 1 :(得分:4)

这是:

var totals = table
    .SelectMany(_ => _)
    .GroupBy(_ => _.Key, _ => _.Value)
    .ToDictionary(
        group => group.Key,
        group => group.Aggregate(AggregationFunc));