我有一个类:
class Spline
int ChildrenCount;
Spline GetChild (int index)
class SplineCollection : IEnumerable<Spline>
Spline Master
是否有可能为SplineCollection写一个递归的IEnumerable,它会逐个返回所有的孩子?
编辑:所以Master是根Box,其子级的层次结构可以是任何深度。
编辑:通过使用名称Box,我认为我困惑了一些人。它意味着是一个几何对象,而不是一个容器。因此将其更改为Spline。答案 0 :(得分:10)
我会手动维护堆栈,而不是依赖于调用堆栈。原因是,如果您通过递归调用获取后代的方法使用调用堆栈,则必须为访问的每个IEnumerable<Spline>
创建新的Spline
。那将是低效的。您可以使用自己的堆栈来显着改善遍历。
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));
}
}
}
}
答案 1 :(得分:9)
这将对Box
'树'进行深度优先遍历。然后,您可以在Master
框中调用此方法以返回所有递归子项。
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;
}
}
}
}
答案 2 :(得分:3)
是的 - 请参阅本节了解Recursive Iterations使用C#迭代器。
答案 3 :(得分:1)
class Box
{
int ChildrenCount;
Box GetChild (int index){/* some implementation*/}
public IEnumerable<Box> Children
{
get
{
for(int i = 0; i != ChildrenCount; ++i)
yield return GetChild(i);
}
}
public IEnumerable<Box> Descendants
{
get
{
foreach(Box child in Children)
{
yield return child;
foreach(Box desc in child.Descendants)
yield return desc;
}
}
}
}
你可以从BoxCollection中调用它,但由于Box已经是Box的集合,我不知道BoxCollection的用途是什么。就此而言,拥有Box实现IEnumerable<Box>
或其后代之一(ICollection<Box>
,IList<Box>
)可能会提高实用性。
也可以以迭代而不是递归的方式进行,有时候性能更好(几乎任何时候编译器都不会将递归转换为交互),但递归更具可读性,通常更多不够高效。
答案 4 :(得分:1)
是的,但您必须枚举递归结果。你不能只是回报它,因为类型不匹配。
IEnumerable<int> Triangle(int n) {
yield return n;
if (n > 0)
foreach (var e in Triangle(n - 1))
yield return e;
}
答案 5 :(得分:0)
这增加了Brian Gideon的很好的回答,实际上只提供了后代,没有根元素。此外,它使用foreach
,例如在EF上下文中可用。
这是我的代码():
/// <summary>
/// Retrieves all descendants.
/// </summary>
public IEnumerable<Item> Descendants {
get {
// This performs a simple iterative preorder traversal.
Stack<Item> stack = new Stack<Item>(this.Children);
while (stack.Count > 0) {
Itemcurrent = stack.Pop();
yield return current;
//Push current's children
foreach (Item currentChild in current.Children) {
stack.Push(currentChild);
}
}
}
}
答案 6 :(得分:-1)
不确定。你甚至不需要BoxContainer,因为box的名称存在于容器中:
public class Box
{
private List<Box> myBoxes;
public IEnumerable<Box> GetAllBoxes()
{
yield return this;
foreach (var box in myBoxes)
{
var enumerator = box.GetAllBoxes().GetEnumerator();
while(enumerator.MoveNext())
yield return enumerator.Current;
}
}
}
如果方框A持有方框B和方框C,方框B持有方框D和方框E,方框C方向方框方向为方框F,则可枚举出A,B,D,E,C,F。