Functionally traversing a tree in C#

后端 未结 3 1650
野性不改
野性不改 2021-01-02 19:42

Consider the following extension method in c#, Traverse:

IEnumerable Traverse( this IEnumerable source, 
                                  


        
相关标签:
3条回答
  • 2021-01-02 19:57

    Well I don't think you can avoid searching the tree until you find the node you're looking for without storing a parent pointer.

    You'll start from the root. Test the current node for a match. If it is a match, return the node or just the name (as a list of this one element). Otherwise, if this is a leaf node, return null. If not a leaf, traverse it's children and if the children return non-null value, prepend the current node to your list and return that.

    Returning from the original call, null means no match found. Otherwise you'll have your list of nodes in order.

    0 讨论(0)
  • 2021-01-02 20:01

    I think the trick is to simply not pass down a Node type. Instead pass down the Node and it's qualified path. For example

    var node = GetTheStartNode();
    var start = new { Path = node.Name; Node = node };
    var paths = 
       start
         .Traverse( x => x.Node.Children.Select(
            c => new { .Path = x.Path + ":" c.Name; .Node=c) )
         .Select(x => x.Path);
    
    0 讨论(0)
  • 2021-01-02 20:10

    Clearest and most reusable solution:

    Create a generic method that enumerates all possible pathes:

    static IEnumerable<IEnumerable<T>> ComputePaths<T>(T Root, Func<T, IEnumerable<T>> Children) {
        yield return new[] { Root };
        foreach (var Child in Children(Root)) 
            foreach (var ChildPath in ComputePaths(Child, Children)) 
                yield return new[] { Root }.Concat(ChildPath);            
    }
    

    The resulting enumeration can be easily transformed into your string representation.

        // All paths
        var Paths = ComputePaths(Test, x => x.Children);
    
        // Compute string representation 
        var StrPaths = from p in Paths select string.Join(":", p.Select(t => t.Name).ToArray());
    
        foreach(var p in StrPaths)
            Console.WriteLine(p);
    
    0 讨论(0)
提交回复
热议问题