树遍历通常需要某种递归,并且由于 C# 作为一种语言不支持命名的 lambda 表达式(与命名函数表达式的 JavaScript 概念不同),我想不出在纯 LINQ 中干净地执行此任务的方法使用 lambda 查询。
如果你愿意在外部声明你的函数委托,那是很有可能的。但是,此代码在构建树方面没有提供比传统递归方法明显的优势,但确实演示了 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