Linq projection of a flattened table in a graph of parent and child objects

I have an enumerated list containing a flattened parent-child relationship:

ParentGuid1, ParentName1, ChildGuid1, ChildName1 ParentGuid1, ParentName1, ChildGuid2, ChildName2 ParentGuid2, ParentName2, ChildGuid3, ChildName3 ParentGuid2, ParentName2, ChildGuid4, ChildName4 

I defined a Child class and a parent class that includes a List<Child> property called Children.

Is it possible to use linq to create objects with a single instance of the Parent class on a graph for a unique ParentGuid, referring to a list filled with children associated with this parent.

Something along the lines of this (note that this code does not compile):

 myFlattenedHierarchy.Select(p => new Parent {Guid = p.ParentGuid, Name = p.ParentName, Children = myFlattenedHierarchy.Where(c => c.ParentGuid == p.ParentGuid).Select(c => new Child{Guid = c.ChildGuid, Name = c.ChildName}) }); 
+6
source share
5 answers
 myFlattenedHierarchy.Select(p => new Parent {Guid = p.ParentGuid, Name = p.ParentName, Children = myFlattenedHierarchy.Where(c => c.ParentGuid == p.ParentGuid).Select(c => new Child{Guid = c.ChildGuid, Name = c.ChildName}) }); 

You must do this, but Children cannot be a list, it must be IEnumerable .

+5
source

The pre-Linq method with a simple loop is used here.

 Dictionary<Guid, Parent> parents = new Dictionary<Guid, Parent>(); foreach(RowType row in myFlattenedHierarchy) //just enumerate once { if (!parents.ContainsKey(row.ParentGuid) { Parent newParent = new Parent(row); parents[row.ParentGuid] = newParent; } Child newChild = new Child(row); Parent theParent = parents[row.ParentGuid]; theParent.Children.Add(newChild); } List<Parent> result = parents.Values.ToList(); 

Or you can use GroupBy to get a similar result.

 from row in myFlattenedHierarchy group row by row.ParentGuid into g select new Parent() { Guid = g.Key, Name = g.First().ParentName, Children = ( from childRow in g select new Child() { Guid = childrow.ChildGuid, Name = childrow.ChildName } ).ToList() } 

This is what is more convenient. In any case, do not re-read myFlattenedHierarchy inside the loop / query.

+3
source

I believe you can use GroupBy () (full disclosure: not compiled):

 myFlattenedHierarchy.GroupBy(row => row.ParentGuid) .Select(group => new Parent { Guid = group.Key.ParentGuid, Name = group.Key.ParentName, Children = myFlattenedHierarchy.Where(c => c.ParentGuid == group.Key.ParentGuid) .Select(c => new Child{ Guid = c.ChildGuid, Name = c.ChildName }) .ToList() }); 
+2
source

You need to do recursion and infinite recursion if you have a loop from your flat collection. Linq cannot be used for the full problem, but it can help return a child of a particular node.

0
source

This should work, very similar to David B's second example, but I could not get it to work without some kind of fixation (grouping by multiple columns), so I added it here for the record.

 from row in myFlattenedHierarchy group row by new { row.ParentGuid, row.ParentName } into g select new Parent() { Guid = g.Key.ParentGuid, Name = g.Key.ParentName, Children = ( from childRow in g select new Child() { Guid = childRow.ChildGuid, Name = childRow.ChildName } ).ToList() }; 
0
source

Source: https://habr.com/ru/post/898290/


All Articles