using System; using System.Collections.Generic; using System.Linq; namespace ZeroLevel.Services.Trees { public static class TreesVisitor { /// /// Extract tree branches to plain array /// /// Node type /// Tree root /// Extractor of node children /// Array of tree branches public static List ExtractBranches(T root, Func> childrenExtractor) { if (root == null!) throw new ArgumentNullException(nameof(root)); if (childrenExtractor == null!) throw new ArgumentNullException(nameof(childrenExtractor)); var result = new List(); TraversTreeBrunches(root, childrenExtractor, brunch => { result.Add(brunch.ToArray()); }); return result; } /// /// Selects all branches of the tree, returning an array of branches consisting of the specified node values. /// /// Type of tree nodes /// Value type for returned branch elements /// Root /// Selects child nodes for the current node. /// Select the value of the node /// List of tree branches public static List SpecifyExtractBranches(T root, Func> childrenExtractor, Func codeExtractor) { if (root == null!) throw new ArgumentNullException(nameof(root)); if (childrenExtractor == null!) throw new ArgumentNullException(nameof(childrenExtractor)); if (codeExtractor == null!) throw new ArgumentNullException(nameof(codeExtractor)); var result = new List(); TraversTreeBrunches(root, childrenExtractor, brunch => { result.Add(brunch.Select(i => codeExtractor(i)).ToArray()); }); return result; } /// /// Performs tree branch traversal. /// public static void TraversTreeBrunches(T root, Func> childrenExtractor, Action> handler) { if (root == null!) throw new ArgumentNullException(nameof(root)); if (childrenExtractor == null!) throw new ArgumentNullException(nameof(childrenExtractor)); if (handler == null!) throw new ArgumentNullException(nameof(handler)); var brunch = new List(); brunch.Add(root); foreach (var child in childrenExtractor(root)) { TraversNode(child, brunch, childrenExtractor, handler); } } private static void TraversNode(T node, List brunch, Func> childrenExtractor, Action> handler) { if (node == null!) { handler(brunch); return; } var currentBrunch = new List(brunch); currentBrunch.Add(node); var children = childrenExtractor(node); if (children != null && children.Any()) { foreach (var child in childrenExtractor(node)) { TraversNode(child, currentBrunch, childrenExtractor, handler); } } else { handler(currentBrunch); } } } }