LINQ:如何将嵌套的分层对象转换为展平对象

Mic*_*ync 14 linq

如何使用LINQ将嵌套的分层对象转换为展平对象?我知道我们可以轻松使用foreach循环来实现这一点.但我想知道是否有办法在LINQ中编写它.

class Person{
   public int ID {get;set}
   public string Name {get;set}
   public List<Person> Children {get;}
}
Run Code Online (Sandbox Code Playgroud)

数据:

ID   : 1

Name : Jack

Children

2 | Rose 

3 | Paul
Run Code Online (Sandbox Code Playgroud)

我喜欢将此数据转换为扁平格式,如下所示.

1 | Jack 

2 | Rose 

3 | Paul
Run Code Online (Sandbox Code Playgroud)

我们怎么能用Linq做到这一点?

mqp*_*mqp 17

如果你想让它压扁任意深度的人,我建议如下:

public IEnumerable<Person> GetFamily(Person parent)
{
    yield return parent;
    foreach (Person child in parent.Children) // check null if you must
        foreach (Person relative in GetFamily(child))
            yield return relative;
}
Run Code Online (Sandbox Code Playgroud)

使用LINQ没有任何好方法可以缩短它,因为匿名lambdas不能在不实现Y的情况下递归调用自己.你可以"减少"上面的方法

return parent.Children.SelectMany(p => GetFamily(p))
                      .Concat(new Person[] { parent });
Run Code Online (Sandbox Code Playgroud)

或者

yield return parent;
    foreach (Person relative in parent.Children.SelectMany(GetFamily))
        yield return relative;
Run Code Online (Sandbox Code Playgroud)

但这对我来说似乎没什么必要.

  • 你只是以一种我认为不常见的方式使用单词.我呼吁维基百科页面:http://en.wikipedia.org/wiki/Anonymous_function*"在编程语言理论中,匿名函数(也是函数常量,函数文字或lambda函数)是一个函数(或子程序)定义的,可能被调用的,不受标识符约束."*说"对象没有名称"不是我如何使用"名称"这个词,所以我们仍然会对此持不同意见. (4认同)

小智 9

这是一个很好的,通用的和可重用的扩展方法:

static public IEnumerable<T> Descendants<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> descendBy)
{
    if (!source.IsNullOrEmpty())
    {
        foreach (T value in source)
        {
            yield return value;

            if (!descendBy(value).IsNullOrEmpty())
            {
                foreach (T child in descendBy(value).Descendants<T>(descendBy))
                {
                    yield return child;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,使用这样:

var allChildren = parent.Children.Descendants(p => p.Children);
Run Code Online (Sandbox Code Playgroud)

一个小问题是,它不包括列表中的原始父级,您需要这样做.