2014-01-10 5 views
0

У меня есть эти таблицыГруппировка списка списка с помощью LINQ

public class TaskDetails 
{ 
    public string EmployeeName {get; set;} 
    public decimal EmployeeHours {get; set;} 
} 
public class Tasks 
{ 
    public string TaskName {get; set;} 
    public List<TaskDetails> TaskList {get; set;} 
} 

У меня есть функция, которая возвращает List<Tasks>. Мне понадобится создать новый Список, который группирует EmployeeName и SUMEmployeeHoursнезависимо от того,TaskName. То есть, мне нужно получить TotalHours каждого Сотрудника. Как это получить?

P.S: И к тому, что я сделал до сих пор. Я долго смотрел на код. Упрощенная резиновая утка Решение проблем безрезультатно. Я могу получить результаты, используя foreach и помещая его в Dictionary<string, decimal>. Эта логика будет проверять, нет ли ключа, добавить новый ключ и присвоить значение, и если ключ существует, добавьте десятичное значение в исходное значение. Но я чувствую его слишком много здесь. Я чувствую, что есть комбинация ForEach - GroupBy - Sum, которую мне не хватает.

Любые указатели на то, как это сделать, будут очень полезны для меня.

+0

Ваш код не компилируется. Я получаю сообщение об ошибке '' Tasks ': имена участников не могут быть такими же, как и их закрывающий тип'. Вы не можете иметь свойство «Задачи» в классе «Задачи». – Enigmativity

+0

извините, я абстрагировал проблему и не обратил внимания на опечатку. исправленный. – naveen

ответ

4
var results = tasks.SelectMany(x => x.Tasks) 
        .GroupBy(x => x.EmployeeName) 
        .ToDictionary(g => g.Key, g => g.Sum(x => x.EmployeeHours)); 

Дает Dictionary<string, decimal>.

Чтобы получить список только заменить ToDictionary с Select/ToList цепи:

var results = tasks.SelectMany(x => x.Tasks) 
        .GroupBy(x => x.EmployeeName) 
        .Select(g => new { 
         EmployeeName = g.Key, 
         Sum = g.Sum(x => x.EmployeeHours) 
        }).ToList(); 
+0

спасибо за подробное объяснение. – naveen

3

a SelectMany поможет, я думаю.

Это будет "придавить" в списки TaskDetail всех ваших Task элементов в единый IEnumerable<TaskDetail>

var result = listOfTasks.SelectMany(x => x.Tasks) 
      .GroupBy(m => m.EmployeeName) 
      .Select(m => new { 
       empName = m.Key, 
       hours = m.Sum(x => x.EmployeeHours) 
      }); 
+1

+ 1 Извините, что я не могу отметить несколько – naveen

1
var emplWithHours = allTasks 
    .SelectMany(t => t.Tasks) 
    .GroupBy(empl => empl.EmployeeName) 
    .Select(empl => new 
    { 
     EmployeeName = empl.Key, 
     TotalHours = empl.Sum(hour => hour.EmployeeHours) 
    }).ToDictionary(i => i.EmployeeName, i => i.TotalHours); 

Кроме того, когда и ваше имя класса и имя поля Tasks, он дает ошибку времени компиляции:

Error 1 'Tasks': member names cannot be the same as their enclosing type 

Я бы назвал ваш класс Task, так как он представляет собой одну задачу.

+0

извините, я абстрагировал проблему и упустил опечатку. исправленный. – naveen

1

Я хотел бы сделать это следующим образом:

var query = 
(
    from t in tasks 
    from td in t.TaskList 
    group td.EmployeeHours by td.EmployeeName into ghs 
    select new 
    { 
     EmployeeName = ghs.Key, 
     EmployeeHours = ghs.Sum(), 
    } 
).ToDictionary(x => x.EmployeeName, x => x.EmployeeHours); 

Я немного лаконичнее запрос будет следующим образом:

var query = 
(
    from t in tasks 
    from td in t.TaskList 
    group td.EmployeeHours by td.EmployeeName 
).ToDictionary(x => x.Key, x => x.Sum()); 

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

+0

спасибо за это +1 – naveen

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