Some additional answers to these questions. MarcinJuraszek and DamienG.
First, the first two give a contradictory order. To get a good tree search result, just invert the concatenation (put the “source” first).
Secondly, if you are working with an expensive source, such as EF, and want to limit entire branches, Damien's suggestion that you introduce a predicate is good and can still be done with Linq.
Finally, for an expensive source, it may also be useful to pre-select the fields of interest from each node using an injected selector.
Putting it all together:
public static IEnumerable<R> Flatten<T,R>(this T source, Func<T, IEnumerable<T>> children , Func<T, R> selector , Func<T, bool> branchpredicate = null ) { if (children == null) throw new ArgumentNullException("children"); if (selector == null) throw new ArgumentNullException("selector"); var pred = branchpredicate ?? (src => true); if (children(source) == null) return new[] { selector(source) }; return new[] { selector(source) } .Concat(children(source) .Where(pred) .SelectMany(c => Flatten(c, children, selector, pred))); }
Marc L.
source share