How to get node leaf from nested collection using lambda expression

How to get the result from the example below.

public class Parent
{
    public string Id { get; set; }
    public List<Child> Children { get; set; }
}

public class Child : Parent
{
    public bool Isleaf { get; set; }
}
Child c1 = new Child();
c1.Id = "c1";
c1.Isleaf = false;

Child c2 = new Child();
c2.Id = "c2";
c2.Isleaf = true;

Child c11 = new Child();
c11.Id = "c11";
c11.Isleaf = true;

Child c12 = new Child();
c12.Id = "c12";
c12.Isleaf = false;


Child c121 = new Child();
c121.Id = "c121";
c121.Isleaf = true;

c12.Children = new List<Child>() { c121 };
c1.Children = new List<Child>() { c11, c12 };

Parent p = new Parent();
p.Id = "P1";
p.Children = new List<Child>() { c1, c2 };

From the collection above, I want to get a list of all children with a leaf node true ie List leafNode = new List {c2, c11, c21};

+4
source share
6 answers

This solution is based on Igby Largeman, but it uses the stack and removes recursion to prevent:

void FindLeaves(Parent p, ICollection<Child> leaves)
{
    if (p.Children != null) return;

    var toVisit = new Stack<Child>(p.Children());

    while (toVisit.Count > 0) {
        var current = toVisit.Pop(); 

        foreach (var child in current.Children)
        {    
            if (child.Isleaf)
                leaves.Add(child);
            else
                tovisit.Push(child);
        }
    }
}
+1
source

I would not recommend trying to solve this with a lambda expression. A recursive method would probably fit:

void FindLeaves(Parent p, ICollection<Child> leaves)
{
    if (p.Children != null)
        foreach (var child in p.Children)
        {
            if (child.Isleaf)
                leaves.Add(child);
            FindLeaves(child, leaves);
        }
}

var leaves = new List<Child>();
FindLeaves(p, leaves);

, node, , , , , .

if (child.IsLeaf && !leaves.Contains(child) 
    leaves.Add(child)

, :

  • (, ChildA → ChildB → Childâ). ( , , )
  • . ( )
  • , .
+4

IsLeaf

    public bool Isleaf
    {
        get
        {
            return Children.Any();
        }
    }

-, , . RootNode... AllNodes. ...

var leafNodes = rootNode.AllNodes.Where(a => a.Isleaf);

Telnet ASP.NET RadTreeNode , .

http://www.telerik.com/community/forums/aspnet-ajax/treeview/radtreeview-looping.aspx

0

:

Get the children for each parent that has Isleaf = true;

var child1 = Parent.Children.FirstOrDefault(a => a.Isleaf);  // result is c2
var child2 = c12.Children.FirstOrDefault(a => a.Isleaf);     // result is c121
var child3 = c1.Children.FirstOrDefault(a => a.Isleaf);      // result is c11

List leafNode=new List {child1 ,child2 ,child3 };

, → . , foreach. , , - , , . , . foreach.

0
public static class SearcTree
{
    public static IEnumerable<T> GetLeaf<T>(this T rootNode, Func<T, IEnumerable<T>> childrenFunc)
    {
        var childrens = childrenFunc(rootNode);
        var haschild = childrens != null && childrens.Any();
        if (!haschild)
            yield return rootNode;
        else
            foreach (var node in childrenFunc(rootNode))
            {
                foreach (var child in GetLeaf(node, childrenFunc))
                {
                    childrens = childrenFunc(child);
                    haschild = childrenFunc(child) != null && childrens.Any();
                    if (!haschild)
                        yield return child;
                }
            }
    }
}



  //Uses: 
     var allLeaf = p.GetLeaf(root => root.Children);
0

, Teudimundo . , . .

public class Thing
{
    public IEnumerable<Thing> Children { get; set; }
    public bool IsLeaf => Children == null || !Children.Any();
}

, , Thing. Children IsLeaf, , Thing . IEnumerable, .

public static class EnumerableExtensions
{
    public static IEnumerable<TSource> Leaves<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> children, Func<TSource, bool> isLeaf)
    {
        var nodes = new Stack<TSource>(source);
        while (nodes.Any())
        {
            var current = nodes.Pop();
            if(isLeaf(current))
            {
                yield return current;
                continue;
            }
            foreach (var child in children(current))
            {
                if (isLeaf(child))
                {
                    yield return child;
                }
                else
                {
                    nodes.Push(child);
                }
            }
        }
    }
}

, Linq. , Thing, , . .

var leaves = things.Leaves(t => t.Children, t => t.IsLeaf);

things IEnumerable of Thing. new List<Thing>() Thing things. Leaves - , . - Children, . IsLeaf, , , Thing . IEnumerable<Thing>, things. .ToList(), , . , !

0

All Articles