查找所有祖先,直到节点ID

时间:2011-10-06 16:05:48

标签: c# lambda ienumerable

我有一个节点树,我喜欢迭代查找所有祖先,直到树中的给定点(节点)。 这样我就可以将其插入/保存回我的数据库。 到目前为止,我到目前为止已经证明非常有用的东西:

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个调查员吗?

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);