How to flatten tree via LINQ?

后端 未结 14 2192
抹茶落季
抹茶落季 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:54

    I found some small issues with the answers given here:

    • What if the initial list of items is null?
    • What if there is a null value in the list of children?

    Built on the previous answers and came up with the following:

    public static class IEnumerableExtensions
    {
        public static IEnumerable Flatten(
            this IEnumerable items, 
            Func> getChildren)
        {
            if (items == null)
                yield break;
    
            var stack = new Stack(items);
            while (stack.Count > 0)
            {
                var current = stack.Pop();
                yield return current;
    
                if (current == null) continue;
    
                var children = getChildren(current);
                if (children == null) continue;
    
                foreach (var child in children)
                    stack.Push(child);
            }
        }
    }
    

    And the unit tests:

    [TestClass]
    public class IEnumerableExtensionsTests
    {
        [TestMethod]
        public void NullList()
        {
            IEnumerable items = null;
            var flattened = items.Flatten(i => i.Children);
            Assert.AreEqual(0, flattened.Count());
        }
        [TestMethod]
        public void EmptyList()
        {
            var items = new Test[0];
            var flattened = items.Flatten(i => i.Children);
            Assert.AreEqual(0, flattened.Count());
        }
        [TestMethod]
        public void OneItem()
        {
            var items = new[] { new Test() };
            var flattened = items.Flatten(i => i.Children);
            Assert.AreEqual(1, flattened.Count());
        }
        [TestMethod]
        public void OneItemWithChild()
        {
            var items = new[] { new Test { Id = 1, Children = new[] { new Test { Id = 2 } } } };
            var flattened = items.Flatten(i => i.Children);
            Assert.AreEqual(2, flattened.Count());
            Assert.IsTrue(flattened.Any(i => i.Id == 1));
            Assert.IsTrue(flattened.Any(i => i.Id == 2));
        }
        [TestMethod]
        public void OneItemWithNullChild()
        {
            var items = new[] { new Test { Id = 1, Children = new Test[] { null } } };
            var flattened = items.Flatten(i => i.Children);
            Assert.AreEqual(2, flattened.Count());
            Assert.IsTrue(flattened.Any(i => i.Id == 1));
            Assert.IsTrue(flattened.Any(i => i == null));
        }
        class Test
        {
            public int Id { get; set; }
            public IEnumerable Children { get; set; }
        }
    }
    

提交回复
热议问题