Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to get deepest level nodes in a treeview

Tags:

c#

vb.net

linq

Suppose I have a WinForms Treeview that looks as follows:

Parent1
   Child1
      Sub-Child1
         DeepestNode1
         DeepestNode2
         DeepestNode3
      Sub-Child2
         DeepestNode4
         DeepestNode5
         DeepestNode6
   Child2
      Sub-Child3
      Sub-Child4
      Sub-Child5
      Sub-Child6
   Child3
      (no children)

I would like to create a function along the lines of:

Function GetDeepestChildren(MyNode as Treenode) as List(Of Treenode)

Where, if the results would look like:

GetDeepestChildren(Parent1) = {DeepestNode1, DeepestNode2, DeepestNode3, DeepestNode4, DeepestNode5, DeepestNode6}

GetDeepestChildren(Sub-Child1) = {DeepestNode1, DeepestNode2, DeepestNode3}

GetDeepestChildren(Child2) = {Sub-Child3, Sub-Child4, Sub-Child5, Sub-Child6}

GetDeepestChildren(Child3) = Empty list

... In other words, always go to the deepest level you can from the node given and return the children - Even if they're split between different parents (as was the case in Parent1).

I have created a function that will tell me how many levels deeper a node goes that looks like:

    Public Function GetDeepestChildNodeLevel(ByVal ParentNode As TreeNode) As Integer
        Dim subLevel = ParentNode.Nodes.Cast(Of TreeNode).Select(Function(subNode) GetDeepestChildNodeLevel(subNode))
        Return If(subLevel.Count = 0, 0, subLevel.Max() + 1)
    End Function

So I know from what level to get the children, what i'm looking for is a function that can do this - Somethign along the lines of:

Function GetDeepestChildren(MyNode as Treenode) as List(Of Treenode)
       Return All child nodes where level = GetDeepestChildNodeLevel(MyNode)
End function

I hope this makes sense - Thanks!

like image 907
John Bustos Avatar asked Jan 03 '13 15:01

John Bustos


1 Answers

In C# you can do it with yield return or with a recursive lambda. Here is an example of the second approach:

Func<TreeNode,IEnumerable<TreeNode>> getChildren = null;
getChildren = n => {
    if (n.Nodes.Count != 0) {
        var list = new List<TreeNode>(n.Nodes.Where(c => c.Nodes.Count == 0));
        foreach (var c in n.Nodes) {
            // Note the recursive call below:
            list.AddRange(getChildren(c));
        }
        return list;
    } else {
        return new TreeNode[0];
    }
};
var res = getChildren(myTree);
like image 147
Sergey Kalinichenko Avatar answered Sep 28 '22 15:09

Sergey Kalinichenko