使用LAMBDA编写LINQ查询以在列表中首先放置父项(因为父子依赖项)的正确方法是什么?
例如,预期输出应该是一个有序列表(对象类型名为'层次结构),其中包含所有字段ID,类型字符串的父类):
答案 0 :(得分:0)
树遍历通常需要某种递归,并且由于C#作为一种语言不支持命名的lambda表达式(与命名函数表达式的JavaScript概念不同),我认为无法在纯LINQ中干净地执行此任务使用lambdas进行查询。
如果您愿意在外部声明您的函数委托,则很有可能。但是,此代码没有为构建树的传统递归方法提供明显的优势,但确实演示了LINQ / lambda版本的实现。
以下是使用递归和查找表(效率)的示例:
IEnumerable<ItemType> items = new[]
{
new ItemType() { ID = "A4", ParentID = "A5"},
new ItemType() { ID = "A5", ParentID = "A2"},
new ItemType() { ID = "A1", ParentID = "A2"},
new ItemType() { ID = "A3", ParentID = "A2"},
new ItemType() { ID = "A2", ParentID = null },
};
var childrenLookup = items.ToLookup(i => i.ParentID);
Func<ItemType, IEnumerable<ItemType>> preOrderTraverse = null;
preOrderTraverse = new Func<ItemType, IEnumerable<ItemType>>(item =>
{
var curNode = Enumerable.Repeat(item, 1);
var childNodes = childrenLookup[item.ID]
.OrderBy(i => i.ID) // Sort siblings by ID
.SelectMany(preOrderTraverse);
return Enumerable.Union(curNode, childNodes);
});
var preOrderTraversal = childrenLookup[null].SelectMany(preOrderTraverse);
foreach(var item in preOrderTraversal)
Console.WriteLine($"{item.ID}, {item.ParentID}");
代码的输出是:
A2, A1, A2 A3, A2 A5, A2 A4, A5