How to flatten tree via LINQ?

后端 未结 14 2380
抹茶落季
抹茶落季 2020-11-22 04:56

So I have simple tree:

class MyNode
{
 public MyNode Parent;
 public IEnumerable Elements;
 int group = 1;
}

I have a I

14条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 05:55

    Update:

    For people interested in level of nesting (depth). One of the good things about explicit enumerator stack implementation is that at any moment (and in particular when yielding the element) the stack.Count represents the currently processing depth. So taking this into account and utilizing the C#7.0 value tuples, we can simply change the method declaration as follows:

    public static IEnumerable<(T Item, int Level)> ExpandWithLevel(
        this IEnumerable source, Func> elementSelector)
    

    and yield statement:

    yield return (item, stack.Count);
    

    Then we can implement the original method by applying simple Select on the above:

    public static IEnumerable Expand(
        this IEnumerable source, Func> elementSelector) =>
        source.ExpandWithLevel(elementSelector).Select(e => e.Item);
    

    Original:

    Surprisingly no one (even Eric) showed the "natural" iterative port of a recursive pre-order DFT, so here it is:

        public static IEnumerable Expand(
            this IEnumerable source, Func> elementSelector)
        {
            var stack = new Stack>();
            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();
            }
        }
    

提交回复
热议问题