Click here to Skip to main content
11,709,366 members (38,694 online)
Click here to Skip to main content

Tagged as

Select Recursive Extension method

, 2 May 2011 CPOL 10K 1
Rate this:
Please Sign up or sign in to vote.
An extension method to the IEnumerable`1 interface that can select all children recursively of an entity in a tree like structure
This is an extension method to the IEnumerable`1 interface that can select all children recursively of an entity in a tree like structure.

Example


var allChildren = node.ChildNodes.SelectRecursive(n => n.ChildNodes);

/// <summary>
/// A set of <see cref="T:System.Collections.Generic.IEnumerable`1" /> extensions methods
/// </summary>
public static class IEnumerableExtensions
{
    /// <summary>
    /// Projects each element of a sequence recursively to an <see cref="T:System.Collections.Generic.IEnumerable`1" />
    /// and flattens the resulting sequences into one sequence.
    /// </summary>
    /// <typeparam name="T">The type of the elements.</typeparam>
    /// <param name="source">A sequence of values to project.</param>
    /// <param name="selector">A transform function to apply to each element.</param>
    /// <returns>
    /// An <see cref="T:System.Collections.Generic.IEnumerable`1" /> whose elements
    /// who are the result of invoking the recursive transform function on each element of the input sequence.
    /// </returns>
    /// <example>
    /// node.ChildNodes.SelectRecursive(n => n.ChildNodes);
    /// </example>
    public static IEnumerable<IRecursion<T>> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
    {
        return SelectRecursive(source, selector, null);
    }
    /// <summary>
    /// Projects each element of a sequence recursively to an <see cref="T:System.Collections.Generic.IEnumerable`1" />
    /// and flattens the resulting sequences into one sequence.
    /// </summary>
    /// <typeparam name="T">The type of the elements.</typeparam>
    /// <param name="source">A sequence of values to project.</param>
    /// <param name="selector">A transform function to apply to each element.</param>
    /// <param name="predicate">A function to test each element for a condition in each recursion.</param>
    /// <returns>
    /// An <see cref="T:System.Collections.Generic.IEnumerable`1" /> whose elements are the result of
    /// invoking the recursive transform function on each element of the input sequence.
    /// </returns>
    /// <example>
    /// node.ChildNodes.SelectRecursive(n => n.ChildNodes, m => m.Depth < 2);
    /// </example>
    public static IEnumerable<IRecursion<T>> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector, Func<IRecursion<T>, bool> predicate)
    {
        return SelectRecursive(source, selector, predicate, 0);
    }
    private static IEnumerable<IRecursion<T>> SelectRecursive<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> selector, Func<IRecursion<T>, bool> predicate, int depth)
    {
        var q = source
            .Select(item => new Recursion<T>(depth, item))
            .Cast<IRecursion<T>>();
        if (predicate != null)
            q = q.Where(predicate);
        foreach (var item in q)
        {
            yield return item;
            foreach (var item2 in SelectRecursive(selector(item.Item), selector, predicate, depth + 1))
                yield return item2;
        }
    }
    private class Recursion<T> : IRecursion<T>
    {
        private int _depth;
        private T _item;
        public int Depth
        {
            get { return _depth; }
        }
        public T Item
        {
            get { return _item; }
        }
        public Recursion(int depth, T item)
        {
            _depth = depth;
            _item = item;
        }
    }
}
 
/// <summary>
/// Represents an item in a recursive projection.
/// </summary>
/// <typeparam name="T">The type of the item</typeparam>
public interface IRecursion<T>
{
    /// <summary>
    /// Gets the recursive depth.
    /// </summary>
    /// <value>The depth.</value>
    int Depth { get; }
    /// <summary>
    /// Gets the item.
    /// </summary>
    /// <value>The item.</value>
    T Item { get; }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Magnus_
Web Developer
Sweden Sweden
Software developer

You may also be interested in...

Comments and Discussions

 
GeneralNice one Pin
Shahriar Iqbal Chowdhury2-May-11 10:16
memberShahriar Iqbal Chowdhury2-May-11 10:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150819.1 | Last Updated 2 May 2011
Article Copyright 2010 by Magnus_
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid