Daniel Daniel - 4 months ago 32
C# Question

C# LINQ select hierarchy from list where root has a certain property value

I have a class with the following properties:


  • int ID

  • int? ParentID

  • bool? NeedsShowing



I have a list of these objects, which list represents multiple hierarchies: ID is the key value while ParentID is acting as a foreign key. NeedsShowing is only filled at the root level of each hierarchy, meaning it is only present when
ParentID == null
.

What I need to accomplish - preferably with the simplest possible LINQ - is to select only those hierarchies in the list, where
NeedsShowing == true
(basically applying a filter).

I have approximately 50,000 objects in the list representing roughly 13,000 hierarchies.

Code



Public Class FileHierarchy
{
int ID { get; set; }
int? ParentID { get; set; }
bool? NeedsShowing { get; set; }
}


List of FileHierarchy class with values:

ID ParentID NeedsShowing
----------------------------------
1 null true
2 1 null
3 1 null
4 2 null
5 null false
6 5 null
7 6 null
8 null true
9 8 null


This means I have three hierarchies with root node ID 1, 5, 8 (where
parent ID == null
). I only want to get all nodes in hierarchies with root ID 1 and 8, because root ID 5 has
NeedsShowing == false
.

Answer

Try this

List<FileHierarchy> mylist = GetList();
var selected = mylist.Where(s => s.NeedsShowing.HasValue && s.NeedsShowing.Value);
var children = mylist.Where(c => c.ParentID.HasValue && selected.Select(s => s.ID).Contains(c.ParentID.Value));
var unselected = mylist.Except(selected);
while (children.Any())
{
    unselected = unselected.Except(children);
    var childChild = unselected.Where(c => c.ParentID.HasValue && children.Select(s => s.ID).Contains(c.ParentID.Value));
    selected = selected.Union(children);
    children = childChild;
}