/// <summary> /// Производит выборку поддеревьев узла, указанного <paramref name="hnd"/>. /// <para>Порядок обхода — breadth-first.</para> /// </summary> /// <typeparam name="T">Тип узла дерева.</typeparam> /// <param name="hnd"> /// Узел. /// </param> /// <param name="predicate">Предикат выборки поддерева.</param> /// <param name="childrenSelector">Селектор дочерных узлов.</param> /// <returns>Объект <see cref="IEnumerable{T}"/>.</returns> public static IEnumerable <T> Subtrees <T>(this SingleTreeNodeUtilitiesHandle <T> hnd, Func <T, bool> predicate, Func <T, IEnumerable <T> > childrenSelector) { predicate.EnsureNotNull(nameof(predicate)); childrenSelector.EnsureNotNull(nameof(childrenSelector)); // if (predicate(arg: hnd.Source)) { yield return(hnd.Source); } else { var traversal = new Queue <T>(collection: hnd.Source.Sequence()); for (; traversal.Count > 0;) { var current = traversal.Dequeue(); foreach (var child in childrenSelector(arg: current).EmptyIfNull()) { if (predicate(child)) { yield return(child); } else { traversal.Enqueue(child); } } } } }
public static IEnumerable <T> Ancestors <T>(this SingleTreeNodeUtilitiesHandle <T> hnd, Func <T, T> parentSelector) { parentSelector.EnsureNotNull(nameof(parentSelector)); // var parent = parentSelector(hnd.Source); for (; parent != null;) { yield return(parent); parent = parentSelector(parent); } }
public static TResult Transform <TSource, TResult>(this SingleTreeNodeUtilitiesHandle <TSource> hnd, Func <TSource, IEnumerable <TSource> > childrenSelector, Func <TSource, IEnumerable <TResult>, TResult> transform) { childrenSelector.EnsureNotNull(nameof(childrenSelector)); transform.EnsureNotNull(nameof(transform)); // var root = new P_TreeNodeTransformState <TSource, TResult>(hnd.Source); var traversalStack = new Stack <P_TreeNodeTransformState <TSource, TResult> >(root.Sequence()); for (; traversalStack.Count > 0;) { var currentTraversalEntry = traversalStack.Peek(); // var initialSizeOfTraversalStack = traversalStack.Count; if (currentTraversalEntry.SourceChildren == null) { currentTraversalEntry.SourceChildren = childrenSelector(currentTraversalEntry.Source) .EmptyIfNull() .ToArray(); for (var i = currentTraversalEntry.SourceChildren.Length - 1; i > -1; i--) { traversalStack .Push( new P_TreeNodeTransformState <TSource, TResult>( currentTraversalEntry, currentTraversalEntry.SourceChildren[i])); } } // if (initialSizeOfTraversalStack == traversalStack.Count) { traversalStack.Pop(); if (!ReferenceEquals(currentTraversalEntry, root)) { currentTraversalEntry .Parent .TransformedSourceChildren .Add(transform(currentTraversalEntry.Source, currentTraversalEntry.TransformedSourceChildren)); } } } return(transform(root.Source, root.TransformedSourceChildren)); }
public static IEnumerable <T> Descendants <T>(this SingleTreeNodeUtilitiesHandle <T> hnd, Func <T, IEnumerable <T> > childrenSelector) { childrenSelector.EnsureNotNull(nameof(childrenSelector)); // var traversalBuffer = new Queue <T>(); foreach (var child in childrenSelector(arg: hnd.Source).EmptyIfNull()) { traversalBuffer.Enqueue(child); } for (; traversalBuffer.Count > 0;) { var current = traversalBuffer.Dequeue(); foreach (var child in childrenSelector(current).EmptyIfNull()) { traversalBuffer.Enqueue(child); } yield return(current); } }
public static IEnumerable <T> SelfAndDescendants <T>(this SingleTreeNodeUtilitiesHandle <T> hnd, Func <T, IEnumerable <T> > childrenSelector) => Enumerable.Concat(first: hnd.Source.Sequence(), second: Descendants(hnd: hnd, childrenSelector: childrenSelector));
public static IEnumerable <T> SelfAndAncestors <T>(this SingleTreeNodeUtilitiesHandle <T> hnd, Func <T, T> parentSelector) => Enumerable.Concat(first: hnd.Source.Sequence(), second: Ancestors(hnd: hnd, parentSelector: parentSelector));