/Forestry

Implements generic support for tree- or forest-like structures.

Primary LanguageC#GNU General Public License v3.0GPL-3.0

Forestry

Implements generic support for tree- or forest-like structures, using two different approaches:

First, there is an enumeration extension, to be used much like LINQ.

Second, there is a visitor approach, to invoke a method for each node in order.

Supports depth-first, breadth-first and bottom-up ordered walks.

Available as a nuget package called Forestry.

Usage Example for the visitor approach

Assuming you have a type to represent a tree node like this class TextNode { public string Id; public string ParentId; }

TextNode[] _nodes = new TextNode[]
{
    new TextNode{ Id = "1", ParentId = null },
    new TextNode{ Id = "11", ParentId = "1" },
    new TextNode{ Id = "12", ParentId = "1" },
    new TextNode{ Id = "2", ParentId = null },
    new TextNode{ Id = "21", ParentId = "2" },
};

// You create a visitor by specifying a child accessor: a method to -
// having a node - fetch child nodes.
IForestVisitor<TextNode> visitor = new ForestVisitor<TextNode>(node =>
    _nodes.Where(n => n.ParentId == node.Id)
);

// With that little help, Forestry can perform various tree or forest
// walks of your tree.
var rootNodes = _nodes.Where(node => node.ParentId == null);
Console.WriteLine("Visiting nodes depth first...");
visitor.VisitDepthFirst(
    rootNodes,
    node => Console.WriteLine(node.Id));

Console.WriteLine("... breadth first ...");
visitor.VisitBreadthFirst(
    rootNodes,
    node => Console.WriteLine(node.Id));

Console.WriteLine("... and bottom up.");
visitor.VisitBottomUp(
    rootNodes,
    node => Console.WriteLine(node.Id));

will print this:

Visiting nodes depth first... 1 11 12 2 21 ... breadth first ... 1 2 11 12 21 ... and bottom up. 21 12 11 2 1

Usage example for the enumerator approach

Assuming the same node collection as above, you can write var rootNodes = target.Where(node => node.ParentId == null); foreach(var node in target.DepthFirst( x => target.Where(other => x.Id.Equals(other.ParentId)), rootNodes) Console.WriteLine(node.Id);

will print 1 11 12 2 21