我有一个节点树,我喜欢迭代查找所有祖先,直到树中的给定点(节点)。 这样我就可以将其插入/保存回我的数据库。 到目前为止,我到目前为止已经证明非常有用的东西:
public IEnumerable<INode> Ancestors()
{
var parent = this.Parent;
while (parent != null)
{
yield return parent;
parent = parent.Parent;
}
}
我想,我应该传递一个Func或Func来停止/打破序列。
最佳实施是什么?.Ta
编辑:鉴于以下答案。我正在考虑采取更高效的方式:
public IEnumerable<INode> Ancestors(Func<INode, bool> predicate)
{
var parent = this.Parent;
while (parent != null)
{
if (predicate(parent))
{
yield return parent;
}
else
{
yield break;
}
parent = parent.Parent;
}
}
我说对了Jon的答案会产生2个调查员吗?
答案 0 :(得分:4)
怎么样:
var desiredNode = child.Ancestors().FirstOrDefault(node => node.Id == desiredId);
如果找不到正确的节点,则给null
。
编辑:好的,如果你需要从下到上的完整序列,你可以使用:
var nodes = child.Ancestors().TakeUntil(node => node.Id == desiredId);
其中TakeUntil
是类似TakeWhile
的方法,但包含与谓词匹配的最终节点。您可以在sample implementation中找到MoreLINQ。如果您不介意缺少参数验证(MoreLINQ 提供),那么编写起来非常简单:
public static IEnumerable<T> TakeUntil<T>(this IEnumerable<T> source,
Func<T, bool> predicate)
{
foreach (T item in source)
{
yield return item;
if (predicate(item))
{
yield break;
}
}
}
你可以在Ancestors()
方法中构建功能,但它将两个职责混合成一个相对复杂的函数,而不是有两个简单的函数可以与其他简单的函数组合以一般的方式。
答案 1 :(得分:0)
试试这个:
public IEnumerable<INode> Ancestors(Func<INode, bool> takeUntil)
{
var parent = this.Parent;
while (parent != null)
{
yield return parent;
if (takeUntil(parent))
{
break;
}
parent = parent.Parent;
}
}
...
var ancestors = node.Ancestors(n => n.Id == 123);