Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to write a recursive IEnumerable<T>

I have a class like:

class Spline
    int ChildrenCount;
    Spline GetChild (int index)

class SplineCollection : IEnumerable<Spline>
    Spline Master

Is it possible to write a recursive IEnumerable for the SplineCollection where it will return all the children one by one?

EDIT: So Master is the root Box, and the hierarchy of its children can be any depth.

EDIT: By using the name Box, I think I confused some people. It's meant to be a geometric object, not a container. So changing it to Spline.

like image 656
Joan Venge Avatar asked Sep 02 '10 21:09

Joan Venge


3 Answers

I would go with manually maintaining a stack instead of relying on the call stack here. The reason is because a new IEnumerable<Spline> would have to be created for each Spline visited if you used the call stack by recursively calling the method that gets the descendants. That would be inefficient. You can significantly improve the traversal by using your own stack.

public IEnumerable<Spline> Descendants
{
    get
    {
        // This performs a simple iterative preorder traversal.
        var stack = new Stack<Spline>(new Spline[] { this });
        while (stack.Count > 0)
        {
            Spline current = stack.Pop();
            yield return current;
            for (int i = current.ChildrenCount - 1; i >= 0; i--)
            {
                stack.Push(current.GetChild(i));
            }
        }
    }
}
like image 119
Brian Gideon Avatar answered Oct 21 '22 03:10

Brian Gideon


This will do a depth-first traversal of the Box 'tree'. You can then just call this method on the Master box to return all the recursive children.

public class Box
{
    // ...

    public IEnumerable<Box> GetBoxes() 
    {
        yield return this;

        for (int i=0; i<box.ChildrenCount; i++)
        {
            foreach (Box child in box.GetChild(i).GetBoxes())
            {
                 yield return child;
            }
        }
    }
}
like image 9
thecoop Avatar answered Oct 21 '22 02:10

thecoop


Yep - see this section for Recursive Iterations using C# iterators.

like image 3
Steve Michelotti Avatar answered Oct 21 '22 03:10

Steve Michelotti