Сводные столбцы в таблице представлены в виде списка> - PullRequest
0 голосов
/ 24 января 2011

Что такое 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 способ сделать это?

Если нет, то какой самый LINQ-подобный способ определения метода расширения (в словаре) для переноса приведенного выше кода?

Разъяснение : AggregationFunc - этолюбая функция, которая принимает промежуточный итог и следующее значение элемента и создает новый промежуточный итог, например,

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

Ответы [ 2 ]

4 голосов
/ 24 января 2011

Вот оно:

var totals = table
    .SelectMany(_ => _)
    .GroupBy(_ => _.Key, _ => _.Value)
    .ToDictionary(
        group => group.Key,
        group => group.Aggregate(AggregationFunc));
4 голосов
/ 24 января 2011

Я предполагаю, что ваша последняя строка на самом деле:

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. Превратить группы пар ключ-значение в словарь с помощью:
    • "Ключ" - это ключ группы , то есть ключ, общий для всех пар в группе.
    • «Значение» - это совокупность отдельных значений всех пар в группе.
...