1

假设我们有一个具有以下属性的实体:

public class Foo    
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }
}

孩子是具有非空 ParentId 的任何 Foo。可以有多个级别的父/子关系,此时最多为 5 个。

是否有一种简单的 LINQ 方法或通用方法从 Foo 开始并获取它的所有孩子,以及它的孩子的孩子,以及它的孩子的孩子的孩子等等?

目前,我正在遍历初始父母的每个孩子,然后再次循环以获取该孩子的所有孩子,等等。这很乏味,似乎不是完成我想要的正确方法。

4

2 回答 2

1

因此,如果只有一个Foo对象,那么不,您无法获得它的所有后代。至少,您还需要拥有所有 Foo对象的序列,以便找到将该对象作为父对象的节点,因为您的Foo对象还没有对其子对象的引用。如果你确实有这个序列,那么它并不是特别难。

您可以使用ToLookup所有 foo 的序列来为该 ID 值的所有子项创建 ID 查找:

var allFoos = new List<Foo>();

var childrenLookup = allFoos.ToLookup(foo => foo.ParentId);

要获取特定孩子的所有后代的序列,您现在有简单的树遍历:

public static IEnumerable<Foo> Descendants(Foo foo, ILookup<int?, Foo> childrenLookup)
{
    var stack = new Stack<Foo>();
    stack.Push(foo);

    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;

        foreach (var child in childrenLookup[next.Id])
            stack.Push(child);
    }
}
于 2013-07-11T17:12:16.663 回答
1

我更喜欢维护一个字符串属性,它代表层次结构中的一个位置。例如,如果值为“/99/42”,那么您知道该项目属于属于 99 的父项 42。这很好的原因是因为您可以展平整个 Foos 集合并查询该字段那些以“/99”开头的,你会得到层次结构的整个分支。所以你的班级看起来像这样:

public class Foo    
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Path { get; set; } //eg: /99/42
}

希望有帮助。

于 2013-07-11T16:52:43.753 回答