Crispin
Crispin

Reputation: 25

Traversing in a Tree Like Stucture using Linq

I have an object which has a stucture like this :

    public class CustomObject
    {
        public int CustomProperty{get;set;}
        public string CustomStringProperty{get;set;}
        public List<CustomObject> CustomObjects{get;set;}
    }

I know there are lot of way where I can pull up any object, its parent object or getting an object based on the some condition on the CustomProperty.

I want to write some extension Methods or linq so that Client may have access to each object and its properties.

Currently Client has list --> List<CustomObject>();

eg. ClientMethod(List<CustomObject> customObjs);

Upvotes: 1

Views: 295

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205629

Assuming that you want to be able to traverse the items in the list and all their children.

As usual with such questions, I would suggest you to get the highly efficient general tree preorder traversal method from How to flatten tree via LINQ?:

public static partial class TreeHelper
{
    public static IEnumerable<T> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
    {
        var stack = new Stack<IEnumerator<T>>();
        var e = source.GetEnumerator();
        try
        {
            while (true)
            {
                while (e.MoveNext())
                {
                    var item = e.Current;
                    yield return item;
                    var elements = elementSelector(item);
                    if (elements == null) continue;
                    stack.Push(e);
                    e = elements.GetEnumerator();
                }
                if (stack.Count == 0) break;
                e.Dispose();
                e = stack.Pop();
            }
        }
        finally
        {
            e.Dispose();
            while (stack.Count != 0) stack.Pop().Dispose();
        }
    }
}

and utilize it for your needs (you can use a different name if you don't like it):

partial class TreeHelper
{
    public static IEnumerable<CustomObject> Expand(this IEnumerable<CustomObject> source)
    {
        return source.Expand(item => item.CustomObjects != null && item.CustomObjects.Count > 0 ? item.CustomObjects : null);
    }
}

Then you can use simply:

void ClientMethod(List<CustomObject> customObjs)
{
    foreach (var item in customObjs.Expand())
    {
        // do something
    }
}

or LINQ queries like customObjs.Expand().Where(...) etc.

Upvotes: 2

Related Questions