Recursive List Flattening

后端 未结 13 1344
既然无缘
既然无缘 2020-11-27 04:25

I could probably write this myself, but the specific way I\'m trying to accomplish it is throwing me off. I\'m trying to write a generic extension method similar to the oth

13条回答
  •  Happy的楠姐
    2020-11-27 05:08

    I had to implement mine from scratch because all of the provided solutions would break in case there is a loop i.e. a child that points to its ancestor. If you have the same requirements as mine please take a look at this (also let me know if my solution would break in any special circumstances):

    How to use:

    var flattenlist = rootItem.Flatten(obj => obj.ChildItems, obj => obj.Id)
    

    Code:

    public static class Extensions
        {
            /// 
            /// This would flatten out a recursive data structure ignoring the loops. The end result would be an enumerable which enumerates all the
            /// items in the data structure regardless of the level of nesting.
            /// 
            /// Type of the recursive data structure
            /// Source element
            /// a function that returns the children of a given data element of type T
            /// a function that returns a key value for each element
            /// a faltten list of all the items within recursive data structure of T
            public static IEnumerable Flatten(this IEnumerable source,
                Func> childrenSelector,
                Func keySelector) where T : class
            {
                if (source == null)
                    throw new ArgumentNullException("source");
                if (childrenSelector == null)
                    throw new ArgumentNullException("childrenSelector");
                if (keySelector == null)
                    throw new ArgumentNullException("keySelector");
                var stack = new Stack( source);
                var dictionary = new Dictionary();
                while (stack.Any())
                {
                    var currentItem = stack.Pop();
                    var currentkey = keySelector(currentItem);
                    if (dictionary.ContainsKey(currentkey) == false)
                    {
                        dictionary.Add(currentkey, currentItem);
                        var children = childrenSelector(currentItem);
                        if (children != null)
                        {
                            foreach (var child in children)
                            {
                                stack.Push(child);
                            }
                        }
                    }
                    yield return currentItem;
                }
            }
    
            /// 
            /// This would flatten out a recursive data structure ignoring the loops. The     end result would be an enumerable which enumerates all the
            /// items in the data structure regardless of the level of nesting.
            /// 
            /// Type of the recursive data structure
            /// Source element
            /// a function that returns the children of a     given data element of type T
            /// a function that returns a key value for each   element
            /// a faltten list of all the items within recursive data structure of T
            public static IEnumerable Flatten(this T source, 
                Func> childrenSelector,
                Func keySelector) where T: class
            {
                return Flatten(new [] {source}, childrenSelector, keySelector);
            }
        }
    

提交回复
热议问题