LINQ:如何将嵌套的层次对象转换为展平对象
如何使用LINQ将嵌套层次对象转换为展平对象?我知道我们可以很容易地使用foreach循环来实现这一点。但是我想知道是否有一种方法可以用LINQ来写LINQ:如何将嵌套的层次对象转换为展平对象,linq,Linq,如何使用LINQ将嵌套层次对象转换为展平对象?我知道我们可以很容易地使用foreach循环来实现这一点。但是我想知道是否有一种方法可以用LINQ来写 class Person{ public int ID {get;set} public string Name {get;set} public List<Person> Children {get;} } 我喜欢将这些数据转换成如下所示的扁平格式 1 | Jack 2 | Rose 3 | Paul 我
class Person{
public int ID {get;set}
public string Name {get;set}
public List<Person> Children {get;}
}
我喜欢将这些数据转换成如下所示的扁平格式
1 | Jack
2 | Rose
3 | Paul
我们如何使用Linq呢?如果你想让它压扁任意深度的人,我建议如下:
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;
}
或者
yield return parent;
foreach (Person relative in parent.Children.SelectMany(GetFamily))
yield return relative;
但这对我来说似乎有点不必要。这是一种很好的、通用的、可重用的扩展方法:
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;
}
}
}
}
}
一个小缺点是它没有在列表中包含原始父级,您需要这样做。当然,lambdas可以自己调用。下面是使用递归lambda的Fibonacci:
Func fib=null;fib=i=>我说过“匿名lambdas不能调用它们自己”,这就是为什么他不能编写一个表达式来返回他想要的值——他需要声明一个命名函数来递归。因此,通过将匿名的东西放入变量中,它就不再是匿名的了?例如,var a=new{X=5}代码>?我仍然将引用的a
称为匿名类型。微软无条件地这样说,看看第二个例子。几乎所有匿名的东西都必须放在某种命名变量或参数中;否则,代码无法使用它们。这并不意味着它们不是匿名的。我将继续使用“匿名”一词来表示“不通过名称识别”。在您的示例中,类型是匿名的,但对象不是匿名的。您只是以一种我认为不常见的方式使用词。我求助于维基百科页面:“在编程语言理论中,匿名函数(也是函数常量、函数文字或lambda函数)是一个定义的函数(或子例程),可能被调用,而不受标识符的约束。”我不想用“名称”这个词来形容“对象没有名称”,因此,我们在这一点上仍有分歧。
yield return parent;
foreach (Person relative in parent.Children.SelectMany(GetFamily))
yield return relative;
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);