开发者

Finding all ancestors until node id

开发者 https://www.devze.com 2023-04-11 00:25 出处:网络
I have a Node Tree i like to iterate to find all ancestors until a given point (node) in the tree. That way i can inserted/save it back to my db.

I have a Node Tree i like to iterate to find all ancestors until a given point (node) in the tree. That way i can inserted/save it back to my db. So far i have something like the following which has been proven very useful, so far:

public IEnumerable<INode> Ancestors()
{
   var parent = this.Parent;
   while (parent != null)
   {
      yield return parent;
      parent = parent.Parent;
   }
}

I think, I should be passing a Func or Func in order to stop/break the sequence.

What would it be the best implementation?.Ta

Edited: Given the answers below. Im thinking going for something more performant like:

 public IEnumerable<INode> Ancestors(Func<INode, bool> predicate)
 {
    var parent = this.Parent;
    while (parent != null)
    {
      if (predicate(parent))
      { 
         yiel开发者_JS百科d return parent;
      }
      else
      { 
         yield break; 
      }

      parent = parent.Parent;
    }
 }

Am i right saying Jon's answer will create 2 enumerators?


How about:

var desiredNode = child.Ancestors().FirstOrDefault(node => node.Id == desiredId);

That give null if the right node can't be found.

EDIT: Okay, if you need the complete sequence from bottom to top, you can just use:

var nodes = child.Ancestors().TakeUntil(node => node.Id == desiredId);

where TakeUntil is a method like TakeWhile but which includes the final node which matched the predicate. You can find a sample implementation in MoreLINQ. If you don't mind the lack of argument validation (which MoreLINQ does provide), it's very simple to write:

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

You could build the functionality into the Ancestors() method, but it's mixing two responsibilities into one relatively-complex function, instead of having two simple functions which can be composed with other simple functions in a very general way.


Try this:

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号