1

I have these tables

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;} } 

I have a function that returns a List<Tasks>. What I would need is to create a new List that groups the EmployeeNames and SUM the EmployeeHours irrespective of the TaskName. That is, I need to fetch TotalHours of each Employees. How to get that?

P.S: And to what have I done so far. I have stared at the code for a long time. Tried Rubber Duck Problem solving to no avail. I can do get the results using a foreach and placing it to a Dictionary<string, decimal>. That logic will be to check if key does not exist, add a new key and assign the value and if the key exists add the decimal value to the original value. But I feel its too much here. I feel there is a ForEach - GroupBy - Sum combination which I am missing.

Any pointers on how to do it will be very helpful for me.

2
  • Your code doesn't compile. I get the error 'Tasks': member names cannot be the same as their enclosing type. You can't have a Tasks property on the Tasks class. Commented Jan 10, 2014 at 7:55
  • sorry, i was abstracting the issue and overlooked the typo. corrected. Commented Jan 10, 2014 at 8:03

4 Answers 4

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

Gives you Dictionary<string, decimal>.

To get a list just replace ToDictionary with Select/ToList chain:

var results = tasks.SelectMany(x => x.Tasks) .GroupBy(x => x.EmployeeName) .Select(g => new { EmployeeName = g.Key, Sum = g.Sum(x => x.EmployeeHours) }).ToList(); 
Sign up to request clarification or add additional context in comments.

Comments

2

a SelectMany would help, I think.

It will "flatten" the Lists of TaskDetail of all your Task elements into a single 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) }); 

Comments

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); 

Also, when both your class name and field name is Tasks, it gives a compile-time error:

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

I would have named your class Task since it represents a single task.

1 Comment

sorry, i was abstracting the issue and overlooked the typo. corrected.
1

I would do it this way:

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); 

I slightly more succinct query would be this:

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

There are pros and cons to each. I think the first is more explicit, but the second a little neater.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.