Last active
July 10, 2017 14:26
-
-
Save mstum/d3bd19f2c06ea072070806c60b2e4847 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class TreeDrawer | |
{ | |
/// <summary> | |
/// Output a Tree to the console | |
/// </summary> | |
/// <remarks> | |
/// Example Output: | |
/// | |
/// NodeName | |
/// ├─ NodeName | |
/// ├─ NodeName | |
/// │ ├─ NodeName | |
/// │ ├─ NodeName | |
/// │ │ ├─ NodeName | |
/// │ │ └─ NodeName | |
/// │ └─ NodeName | |
/// └ NodeName | |
/// </remarks> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="rootNode">The root node of the tree</param> | |
/// <param name="getNodeName">A func that gets the Name of the node</param> | |
/// <param name="getNodeChildren">A func that gets the Children of the node. Must have an indexer.</param> | |
/// <param name="outputFunc">A func to which we'll send characters as we go. For Console output, use <see cref="Console.Write(string)"/>. Newlines will be sent as \r\n.</param> | |
public static void DrawTree<T>(T rootNode, Func<T, string> getNodeName, Func<T, IList<T>> getNodeChildren, Action<string> outputFunc) | |
{ | |
DrawTreeNode(rootNode, getNodeName, getNodeChildren, outputFunc, 0, new HashSet<int>()); | |
} | |
private static void DrawTreeNode<T>(T node, Func<T, string> getNodeName, Func<T, IList<T>> getNodeChildren, Action<string> outputFunc, int currentIndent, HashSet<int> columnsThatHaveEnded) | |
{ | |
const string HBar = "│"; | |
const string NodeWithFutureSiblings = "├─ "; | |
const string NodeWithoutFutureSiblings = "└─ "; | |
const string ColumnSpacing = " "; | |
for (int i = 0; i < currentIndent - 1; i++) | |
{ | |
outputFunc(columnsThatHaveEnded.Contains(i) ? " " : HBar); | |
outputFunc(ColumnSpacing); | |
} | |
if (currentIndent > 0) | |
{ | |
outputFunc(columnsThatHaveEnded.Contains(currentIndent - 1) ? NodeWithoutFutureSiblings : NodeWithFutureSiblings); | |
} | |
outputFunc(getNodeName(node)); | |
outputFunc("\r\n"); | |
var children = getNodeChildren(node); | |
var cc = children?.Count; | |
if (cc.HasValue && cc.Value > 0) | |
{ | |
for (int ix = 0; ix < cc.Value; ix++) | |
{ | |
var child = children[ix]; | |
if (ix == cc.Value - 1) | |
{ | |
columnsThatHaveEnded.Add(currentIndent); | |
} | |
DrawTreeNode(child, getNodeName, getNodeChildren, outputFunc, currentIndent + 1, columnsThatHaveEnded); | |
} | |
// Reset for the next sibling, since the HashSet is shared between siblings | |
columnsThatHaveEnded.Remove(currentIndent); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment