【问题标题】:How to order parent-child relationship with LAMBDA?如何用 LAMBDA 排序亲子关系?
【发布时间】:2016-07-24 10:23:58
【问题描述】:

使用 LAMBDA 编写 LINQ 查询以将父项(由于父子依赖项)放在列表​​中的正确方法是什么?

例如,预期的输出应该是一个有序列表(名为“层次结构”的对象类型),其中包含所有字段 ID、类型字符串的父级):

  • ID 父级
  • A2 空
  • A1 A2
  • A5 A2(取决于 A2)
  • A3 A2
  • A4 A5(取决于 A5)

【问题讨论】:

  • 列表的类型和列表中的对象是什么?从你写的内容来看,这些是字符串吗?
  • 为什么 A5 在 A1 是列表之前出现(虽然两者共享同一个父级)?输出是否有特定规则?
  • 您的措辞不清楚——据我所知,没有 LAMBDA 查询之类的东西——您是指使用 lambda 表达式的 LINQ 查询还是使用查询表达式的 LINQ 查询?
  • 预期输出是什么?和有序列表?等级制度?究竟是什么?

标签: c# linq recursion lambda tree


【解决方案1】:

树遍历通常需要某种递归,并且由于 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多