使用linq对列表进行分组

时间:2014-01-10 07:36:47

标签: c# 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 SUM 分组EmployeeHours TaskName无关。也就是说,我需要获取每个Employees的TotalHours。怎么做到的?

P.S:到目前为止我做了什么。我已经盯着代码很长一段时间了。尝试橡皮鸭问题解决无济于事。我可以使用foreach获取结果并将其放置到Dictionary<string, decimal>。该逻辑将检查密钥是否不存在,添加新密钥并分配值,如果密钥存在,则将小数值添加到原始值。但我觉得这里太过分了。我觉得我有一个ForEach - GroupBy - Sum组合。

任何有关如何操作的指示对我都非常有帮助。

4 个答案:

答案 0 :(得分: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();

答案 1 :(得分:3)

我认为,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)
             });

答案 2 :(得分: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,因为它代表了一项任务。

答案 3 :(得分: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());

每个人都有利弊。我认为第一个更明确,但第二个更整洁。