gpt4 book ai didi

c# - 在自引用(父子)层次树中查找所有后代

转载 作者:行者123 更新时间:2023-11-30 20:35:52 26 4
gpt4 key购买 nike

这类似于问题 ( Finding parents in a tree hierarchy for a given child LINQ (lambda expression) )。但是,我不需要找到所有祖先,而是需要找到所有后代。

我正在修改 Yacoub 的方法,但只设法将所有后代都放在一个分支中。

    private IEnumerable<UserRole> FindAllChildrenRecursively(List<UserRole> allRoles, UserRole role)
{
var child = allRoles.FirstOrDefault(x => x.ParentId == role.Id);

if (child == null)
return Enumerable.Empty<UserRole>();

return new[] { child }.Concat(FindAllChildrenRecursively(allRoles, child));
}

最佳答案

I am modifying Yacoub's method but only managed to get all descendants in one branch

这是因为这一行:

var child = allRoles.FirstOrDefault(x => x.ParentId == role.Id);

虽然它可能适合寻找单亲 parent ,但不适合寻找多个 child 。

但是您不需要递归迭代器和 allRoles 列表的多次迭代。您可以使用 ToLookup 创建快速查找结构扩展方法然后执行迭代 DFS像这样:

private static IEnumerable<UserRole> FindAllChildren(List<UserRole> allRoles, UserRole role)
{
var childrenByParentId = allRoles.ToLookup(r => r.ParentId);
var stack = new Stack<IEnumerator<UserRole>>();
var e = childrenByParentId[role != null ? role.Id : (int?)null].GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
yield return e.Current;
stack.Push(e);
e = childrenByParentId[e.Current.Id].GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count > 0) stack.Pop().Dispose();
}
}

更好的方法是(遵循 DRY 原则)利用 How to flatten tree via LINQ? 中的通用树辅助方法。 :

public static class TreeUtils
{
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = source.GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var elements = elementSelector(item);
if (elements == null) continue;
stack.Push(e);
e = elements.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}
}

像这样:

private static IEnumerable<UserRole> FindAllChildren(List<UserRole> allRoles, UserRole role)
{
var childrenByParentId = allRoles.ToLookup(r => r.ParentId);
return childrenByParentId[role != null ? role.Id : (int?)null].Expand(r => childrenByParentId[r.Id]);
}

关于c# - 在自引用(父子)层次树中查找所有后代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37441398/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com