tags:

views:

89

answers:

5

Hi All,

How can I get a List from all nodes in a tree using LINQ?

My classes are:

class Node
{
 public class Node()
 {
  Children = new List<Node>();
 }

 public List<Node> Children { get; set;}
}

class Tree
{
 public Tree()
 {
  Roots = new List<Node>();
 }

 List<Node> Roots { get; set;}
}
A: 

Have a look here.

leppie
A: 

You can do this by either adding a traversal method, or by using recursive LINQ with Y-combinator. I personally prefer first approach.

Anton Gogolev
+3  A: 
class Node
    {
    public Node()
    {
        Children = new List<Node>();
    }

    public IEnumerable<Node> GetSubTree()
    {
        return Children.SelectMany(c => c.GetSubTree()).Concat(new[] { this });
        //Post-order traversal
    }

    public List<Node> Children { get; set; }
}

class Tree
{
    public Tree()
    {
        Roots = new List<Node>();
    }

    public IEnumerable<Node> GetAllNodes()
    {
        return Roots.SelectMany(root => root.GetSubTree());
    }

    List<Node> Roots { get; set; }
}

How can a tree have more than one root though? Isn't this a forest?

Ani
@Homan Func<Tree, IEnumerable<Node>> nodesForTree = tree => tree.GetAllNodes();Is that what you want? Why though?
Ani
@Ani Thank you for your response, I'll use your code, I was want to make a query without changing the class body, in other words, create the function GetSubTree before the query and use it in the query without changing the class.anyway, thank you again :)
Homam
@ Homan: I understand. If that is what your requirement, you could easily put these methods in a separate class, since they only require access to public properties. You could mark them as extension methods to simpify usage syntax.
Ani
+1  A: 
var allNodes = yourTree.Roots.SelectMany(x => x.TraverseTree(y => y.Children));

// ...

public static class EnumerableExtensions
{
    public static IEnumerable<T> TraverseTree<T>(
        this T parentNode, Func<T, IEnumerable<T>> childNodesSelector)
    {
        yield return parentNode;

        IEnumerable<T> childNodes = childNodesSelector(parentNode);
        if (childNodes != null)
        {
            foreach (T childNode in
                childNodes.SelectMany(x => x.TraverseTree(childNodesSelector)))
            {
                yield return childNode;
            }
        }
    } 
}
LukeH
A: 

Start on Eric Lippert's blog from the link below:

http://blogs.msdn.com/b/ericlippert/archive/2010/04/19/every-binary-tree-there-is.aspx

This might be a more general discussion than you're looking for, but it will answer your question and a lot more besides...

mavnn