2009-12-21 80 views
14

如何使用LINQ将嵌套的分层对象转换为扁平化对象?我知道我们可以很容易地使用foreach循环来实现这一点。但我想知道是否有方法在LINQ中编写它。LINQ:如何将嵌套的分层对象转换为扁平对象

class Person{ 
    public int ID {get;set} 
    public string Name {get;set} 
    public List<Person> Children {get;} 
} 

数据:

ID : 1 

Name : Jack 

Children 

2 | Rose 

3 | Paul 

我想这个数据转换成扁平化的格式如下图所示。

1 | Jack 

2 | Rose 

3 | Paul 

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

回答

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; 
} 

是不是真的与LINQ缩短这个没有什么好的办法,因为匿名的lambda不能打电话自己没有递归执行Y.你可以 “减少” 上面的方法

return parent.Children.SelectMany(p => GetFamily(p)) 
         .Concat(new Person[] { parent }); 

或可替代

yield return parent; 
    foreach (Person relative in parent.Children.SelectMany(GetFamily)) 
     yield return relative; 

但这对我来说似乎没有必要。

+0

当然lambda可以自称。这是Fibonacci使用递归lambda:'Func fib = null; fib = i => i <= 1? i:fib(i-1)+ fib(i-2);' – 2012-08-27 12:36:02

+1

我说“匿名* lambda不能调用自己”,这就是为什么他不能写一个表达式来返回他想要的值 - - 他需要声明一个命名的函数来递归。 – mquander 2012-08-28 03:16:10

+0

因此,通过在变量中放置匿名内容,它不再是匿名的?例如。 'var a = new {X = 5};'?我仍然会调用'a'引用一个匿名类型。 Microsoft无条件地表示[“lambda表达式是匿名函数”](http://msdn.microsoft.com/zh-cn/library/bb397687.aspx),并查看[匿名方法]的第二个示例(http: //msdn.microsoft.com/en-us/library/0yw3tz5k.aspx)。几乎所有的匿名都必须放在某种指定的变量或参数中;否则它们不能被代码使用。这并不意味着他们不是匿名的。 – 2012-08-28 08:07:43

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; 
       } 
      } 
     } 
    } 
} 

在上述情况下,使用这样的:

var allChildren = parent.Children.Descendants(p => p.Children); 

一个次要尼特的是,它不包括原父母在列表中,你需要这样做。

相关问题