1

我有一堂课

    public class Foo
    {
       public IList<Foo> Items { get; set; }
    }

    public class FooList
    {
       public IList<Foo> Items { get; set; }
    }

我希望能够在一个列表中获取所有 Foo 对象,而不是层次结构。

我试过了

    IEnumerable<Foo> result = Items.SelectMany(f =>  f.Items);

但这只是让我获得了该特定对象中的项目 - 它并没有获得所有子对象中的所有项目。

我也试过

    IEnumerable<Foo> result = Items.SelectMany(t => t)

但我得到了错误:

无法从用法中推断方法“System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func>)”的类型参数。尝试明确指定类型参数。

4

2 回答 2

0

假设您有一个FooList名为的实例fooList

您需要在FooList类中定义这样的方法:

public IEnumerable<Foo> GetRecursiveFoos()
{
    return Items.Concat(Items.SelectMany(x => x.Items));
}

然后打电话

IEnumerable<Foo> result = fooList.GetRecursiveFoos();
于 2012-10-19T09:26:50.510 回答
0

在更一般的情况下可以使用类似“flatten-this-tree”的 LINQ 函数是相当容易的:

public static IEnumerable<T> Flatten<T>(
    this IEnumerable<T> source,
    Func<T, IEnumerable<T>> childSelector)
{
    HashSet<T> added = new HashSet<T>();
    Queue<T> queue = new Queue<T>();
    foreach(T t in source)
        if (added.Add(t))
            queue.Enqueue(t);
    while (queue.Count > 0)
    {
        T current = queue.Dequeue();
        yield return current;
        if (current != null)
        {
            IEnumerable<T> children = childSelector(current);
            if (children != null)
                foreach(T t in childSelector(current))
                    if (added.Add(t))
                        queue.Enqueue(t);
        }
    }
}

然后如果你有一个FooList,你可以使用

var allFoos = myFooList.Items.Flatten(foo => foo.Items);

获取Foo列表中的所有 s,以及他们的所有孩子和他们所有孩子和......

于 2012-10-19T09:33:16.483 回答