如何使用LINQ将嵌套的分层对象转换为展平对象?我知道我们可以轻松使用foreach循环来实现这一点。但我想知道是否有办法在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做到这一点?
答案 0 :(得分: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没有任何好方法可以缩短它,因为匿名lambdas不能在不实现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;
但这对我来说似乎没什么必要。
答案 1 :(得分: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);
一个小问题是,它不包括列表中的原始父级,您需要这样做。