Reputation: 3435
I have the following class which is used to assign tasks to employees.
public class TaskDetails
{
public int TaskGroupId { get; set; }
public int TaskId { get; set; }
public string AssignedTo { get; set; }
public string TaskName { get; set; }
}
Typically we get a list of task groups and who are they assigned to like the following, each task is grouped under TaskGroupId and under each group for each task we have a specific taskid and who is responsible for it.
List<TaskDetails> tasks = new List<TaskDetails>
{
new TaskDetails
{
AssignedTo = "JOHN",
TaskGroupId = 100,
TaskId = 1,
TaskName = "FA"
},
new TaskDetails
{
AssignedTo = "TOM",
TaskGroupId = 100,
TaskId = 1,
TaskName = "FA"
},
new TaskDetails
{
AssignedTo = "JOHN",
TaskGroupId = 100,
TaskId = 2,
TaskName = "GH"
},
new TaskDetails
{
AssignedTo = "TOM",
TaskGroupId = 100,
TaskId = 2,
TaskName = "GH"
},
new TaskDetails
{
AssignedTo = "JOHN",
TaskGroupId = 99,
TaskId = 1,
TaskName = "XY"
},
new TaskDetails
{
AssignedTo = "TOM",
TaskGroupId = 99,
TaskId = 1,
TaskName = "XY"
},
new TaskDetails
{
AssignedTo = "JOHN",
TaskGroupId = 99,
TaskId = 2,
TaskName = "YX"
},
new TaskDetails
{
AssignedTo = "TOM",
TaskGroupId = 99,
TaskId = 2,
TaskName = "YX"
}
};
What I am trying to do is to group each task by TaskGroupId and AssignedTo, however if a task is assigned to more than one person I only need to retrieve one of them back, in the above example, task 1 is assigned to John and Tom but I only need one of them, it does not matter which one (it could be Tom or John). I have tried the following but it is retrieving 4 results and both John and Tom as seen in the screenshot. I could remove the x.AssignedTo from the GroupBy statement which gives me 2 results but then the tasks are then repeated in TaskLegs section, so not useful either.
var result = tasks
.GroupBy(x => new {
x.TaskGroupId,
x.AssignedTo })
.Select(group => new {
GroupDetails = group.Key,
TaskLegs = group
.OrderBy(x => x.TaskId)
.ToList() })
.ToList();
Is there anyway of grouping the results in a way so I can only retrieve one of the results from the grouped resultset? Based on the above example I am trying to get 2 results, one for task group 100 and one for task group 99.
Thanks
Upvotes: 2
Views: 3923
Reputation: 27627
If you only want one item per TaskGroupId
then you only group by that field. Grouping by TaskGroupId
and AssignedTo
means that you will get one group for each combination of the two which is why you are getting four items.
So your query must start:
tasks.GroupBy (x => x.TaskGroupId)
You then have two groups (for TaskGroupId 99 and 100).
You then need to select the data into the form you want. I'm a little unclear on what form this data should take. Should it just have one task under each group? If so something like:
.Select(group => new { TaskGroupId = group.Key, TaskLegs = group.OrderBy(x => x.TaskId).First() }).
If it should have each distinct task in there then you will need to do some more grouping:
.Select(group => new {
TaskGroupId = group.Key,
TaskLegs = group
.GroupBy(x=>x.TaskId)
.Select(y => y.First())
.OrderBy(y=>y.TaskId)
})
This will give you two items, one for each taskgroup. Each of those items will have two items in the TaskLegs, for TaskIds 1 and 2.
Bonus thought:
If you wanted to list all people assigned to a task you could change your definition of TaskLegs to:
TaskLegs = group
.GroupBy(x=>x.TaskId)
.Select(y => new {
TaskId = y.Key,
AssignedTo = y.Select(z => z.AssignedTo)
})
.OrderBy(y=>y.TaskId)
Upvotes: 4
Reputation: 2131
Try this..
var result = tasks.GroupBy(x => new x.TaskGroupId) .Select(group => new { GroupDetails = group.Key, TaskLegs = group.Take(1) }) .ToList();
Upvotes: 0