Find top level parent in a list with LINQ

I have a list of custom objects that have an ID and a ParentID. The list looks something like this.

ParentID     ID
  123        345
  123        456
  456        567
  456        678
  678        789

      

I need a LINQ statement to find the top level parent; that is, all objects where ParentID does not exist as an identifier (in this example there are only 123).

Here is what I have so far and am returning 567 678 789.

parentList = baseList.Where(b => !baseList.Select(o => o.ParentID).Distinct().Contains(b.ID)).ToList();

      

+3


source to share


2 answers


Your current query is trying to find all elements where their id does not match any other parent element id - in other words, you find all childless nodes.

It sounds like what you want is all parent nodes - those whose parent id doesn't match another element id.



var ids = new HashSet<int>(baseList.Select(o => o.ID));
var itemsWithNoParent = baseList.Where(o => !ids.Contains(o.ParentID))
    .ToList();

      

I am using HashSet<>

to provide reasonable performance .Contains()

for large collections.

+4


source


also:

parentList = baseList
  .where(parent => !baseList.Any(possibleParent => possibleParent.ID == parent.ParentID))
  .ToList();

      

I use this a lot for small (less than 100,000) collections.



I might as well add this; how easy is it to create a tree view from this:

public class Node
{
  public int Id { get; set; }
  public int ParentId { get; set; }
  public IEnumerable<Node> Nodes { get; set; }
  public Node ParentNode { get; set; }
}

IEnumerable<Node> nodes = .....

nodeTree = nodes.Select(n =>
{
  n.Nodes = nodes.Where(n2 => n2.ParentId == n.Id).ToList();
  n.ParentNode = nodes.FirstOrDefault(n2 => n2.Id == n.ParentId)
  return n;
})
.Where(n => n.ParentNode == null)
.ToList();

      

+3


source







All Articles