2013-06-28 4 views
1

Есть ли способ сделать это в LINQ - я в настоящее время стучал головой против этого на некоторое время:Pivot стол-эск результат с помощью LINQ

Источник:

var selectedDate = new DateTime(2013, 1, 1); 
var selectedMonth = selectedDate.Month; 
var selectedYear = selectedDate.Year; 

var data = new List<MyClass> 
{ 
    new MyClass { Date = new DateTime(2013, 1, 1), Val1 = 1, Val2 = 2 }, 
    new MyClass { Date = new DateTime(2013, 1, 2), Val1 = 1, Val2 = 2 }, 
    new MyClass { Date = new DateTime(2013, 2, 1), Val1 = 1, Val2 = 2 } 
}; 

Date  | Val1 | Val2 
01/01/2013 | 1 | 2 
02/01/2013 | 1 | 2 
01/02/2013 | 1 | 2 

Результат (суммы каждого Val против Дата/месяц/год):

 | selectedDate | selectedMonth | selectedYear 
Val1 | 1   | 2    | 3 
Val2 | 2   | 4    | 6 
+1

Какой поставщик Linq, Linq-To-Objects, Linq-To-Sql, Linq-To-Entities, ...? Что такое вход, какой желаемый результат? –

+0

Это перечислимый список классов. Извините, я обновлю Q соответственно. –

ответ

0
var result = new List<Result>{ 
    new Result{ 
     Val = "Val1", 
     Date = data.Sum(e => e.Val1 * (e.Date == selectedDate ? 1 : 0)), 
     Month = data.Sum(e => e.Val1 * (e.Date.Month == selectedMonth ? 1 : 0)), 
     Year = data.Sum(e => e.Val1 * (e.Date.Year == selectedYear ? 1 : 0)), 
    }, 
    new Result{ 
     Val = "Val2", 
     Date = data.Sum(e => e.Val2 * (e.Date == selectedDate ? 1 : 0)), 
     Month = data.Sum(e => e.Val2 * (e.Date.Month == selectedMonth ? 1 : 0)), 
     Year = data.Sum(e => e.Val2 * (e.Date.Year == selectedYear ? 1 : 0)), 
    } 
}; 

С Result:

public class Result { 
    public String Val { get; set; } 
    public int Date { get; set; } 
    public int Month { get; set; } 
    public int Year { get; set; } 
} 
+0

'Count (x => ...)' является более удобной альтернативой 'Sum (x => ...? 1: 0)'. – nmclean

+0

Правда, но здесь мы должны умножаться на 'e.Val1'. –

+0

Я пропустил это. Тем не менее, мы могли бы избежать этого, используя 'Where (e => ...). Сумма (e => e.Val1)'. – nmclean

1

Я не думаю, что LINQ это решение, на самом деле. Вы можете легко получить одну развернутую «строку», но вам нужно снова перечислить последовательность, чтобы получить следующую, что не очень эффективно (и не работает, если источник является «ленивым» перечислимым, t хочу сохранить всю последовательность в памяти).

Я думаю, что самым простым, эффективным решением является стандарт foreach. Вы могли бы перевести это в LINQ с помощью Aggregate если вы должны были, но это не было бы так просто:

 var val1 = new Result(); 
     var val2 = new Result(); 
     foreach (var item in data) { 
      if (item.Date == selectedDate) { 
       val1.Date += item.Val1; 
       val2.Date += item.Val2; 
      } 
      if (item.Date.Month == selectedMonth) { 
       val1.Month += item.Val1; 
       val2.Month += item.Val2; 
      } 
      if (item.Date.Year == selectedYear) { 
       val1.Year += item.Val1; 
       val2.Year += item.Val2; 
      } 
     } 

Есть, вероятно, способы это можно было бы сделать более динамичным, но это совсем другой вопрос.

Смежные вопросы