How to group multiple items using GroupBy ()?

Consider the following simplified objects and relationships:

public class Job{ int JobId; String name; String status; Discipline disc; WorkCategory workCat; } public class Discipline { int DisciplineId; String DisciplineName; } public class Workcategory{ int WorkCategoryId; String WorkCategoryName; } public Class Grouping{ Discipline parent; List<Workcategory> children; } 

The above model is related to the fact that a Job is associated with one Discipline and one WorkCategory . WorkCategory always a child of a specific parent Discipline (one-to-many relationship). We can assume that the relationship between the assigned discipline and the working category will always be valid.

The problem I am facing is when I try to create a Grouping result Grouping based on the filters that apply to Jobs . I am not sure if this can be done or if the approach I am taking is even correct. The exact question itself is not clear, but the above determines the formulation of the problem.

  • Can the design be improved?
  • How can I group assignments by discipline and work category?
  • Do I need a Grouping class?

I tried the following (this is my first attempt using Linq), but to no avail since my understanding is not complete enough. Another alternative is to get a Discipline group and loop through the original grouping that collects the corresponding WorkCategory .

 var grouping = repository.GetJobsWithActiveStatus() .GroupBy(x => new { x.Discipline.DisciplineID, x.Discipline.DisciplineName, x.Category.WorkCategoryID, x.Category.WorkCategoryName }) .Select(g => new Grouping{ Discipline = new Discipline{ DisciplineID = g.Key.DisciplineID, Name = g.Key.DisciplineName }, Categories = ?? // this is where I am lost }}); 

Edit: After posting this post, I realized that the inital GroupBy parameters result in one group of elements, while I am looking for the result of Group-SubGroup.

Edit 2: To clarify things a bit more, I don’t want related tasks to be performed as part of the result, but rather the Discipline-Workcategory group - therefore the reason for the Grouping class


Original solution based on @Obalix

Change 7-Mar-2010:

This solution does not work - GroupBy on the Discipline object will give a unique grouping for each object. I think this is due to the fact that it is a reference type. I'm right? At first, I accepted this as an answer, but after some head realized that my layout data itself was erroneous. Initial questions are still answered.

 var result = repository.GetJobsWithActiveStatus() .GroupBy(x => x.disc) .Select(g => new Grouping { Discipline = g.Key, Catergories = g.GroupBy(x=>x.workCat) // <--- The Problem is here, grouping on a reference type .Select(l=>l.Key) // needed to select the Key only .ToList() }); 
+6
design c # linq group-by
source share
4 answers

Here is a description of how you can implement the hierarchical grouping mechanism.

The general way to do this is with LINQ (as shown in the link):

 var list = new List<Job>(); var groupedList = list.GroupBy(x => x.disc) .Select(g => new { Key = g.Key, Count = g.Count(), WorkCategoryGroups = g.GroupBy(x => x.workCat) }); 

However, the link also describes an alternative way that allows you to do the following:

 var groupedList = list.GroupByMany(x => x.disc, x => x.workCat); 

Edit: The following remark by Ahmad is a strongly typed version:

 var groupedList = list.GroupBy(x => x.disc) .Select(g => new Grouping { parent = g.Key, children = g.GroupBy(x => x.workCat).ToList() }); 
+2
source share

I would use Linq syntax:

 var jobsByDiscipline = from j in repository.GetJobsWithActiveStatus() group j by j.Discipline.DisciplineID into g select new { DisciplineID = g.Key, Jobs = g.ToList() }; var jobsByCategory = from j in repository.GetJobsWithActiveStatus() group j by j.Workcategory.WorkcategoryID into g select new { WorkcategoryID = g.Key, Jobs = g.ToList() }; 

It seems to me that reading is easier than many riveted methods with parameters of a lambda function.

You can get your groupings from this:

 var disciplineAndCategory = from j in repository.GetJobsWithActiveStatus() group j by j.Discipline.DisciplineID into g let categories = from j2 in g select j2.Workcategory.WorkcategoryID select new { DisciplineID = g.Key, Jobs = categories.Distinct() // each category id once }; 
+2
source share

Here is another way that does not require a Grouping class.

 ILookup<Discipline, Workcategory> result = repository .GetJobsWithActiveStatus() .Select(job => new {disc = job.disc, workCat = job.workCat}) .Distinct() .ToLookup(x => x.disc, x => x.workCat); 
0
source share

This is a solution that works for me.

First I needed to collect all the discipline groups, and then create the appropriate lists of work categories where discipline ID is equal.

 var result = liveJobs .GroupBy(x => new { x.disc.DisciplineID, x.disc.DisciplineName }) .Select(g => new Grouping() { parent = new Discipline(g.Key.DisciplineID,g.Key.DisciplineName), children = g.Where(job=>job.disc.DisciplineID == g.Key.DisciplineID) // filter the current job discipline to where the group key disciplines are equal .Select(j=>j.workCat) .ToList() }); 
0
source share

All Articles