Roy*_*mir 5 c# recursion ienumerable
我写了一个递归函数,产生了 IEnumerable<int>
IEnumerable<int> Go(int b )
{
if (b==0) yield return 0;
else
foreach (var element in Go(b-1))
{
yield return element;
}
}
Run Code Online (Sandbox Code Playgroud)
所以,如果我写
foreach (var element in Go(3))
{
Console.WriteLine (element);
}
Run Code Online (Sandbox Code Playgroud)
它应该屈服
0
1
2
3
Run Code Online (Sandbox Code Playgroud)
但它没有按预期工作.(它显示0).
在正常的递归函数(返回int - 没有Ienumerable)中,它工作正常.
题:
如何修复代码以使其产生预期值?
NB.不,没有理由使用递归的Ienumerables.在玩递归收益后,我才想到这一点.
Bla*_*ear 11
因为你永远不会屈服于b本身而只会屈服于0.
IEnumerable<int> Go(int b)
{
if(b > 0) {
foreach (var element in Go(b-1))
yield return element;
}
yield return b;
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果你想要得到的序列从0开始,向上走,你必须yield return b
经过的foreach
.让我们展开第一个电话Go(3)
:
Go(3):
foreach(var element in Go(2)):
yield return element;
yield return 3;
Run Code Online (Sandbox Code Playgroud)
所以3将是序列中的最后一项(因为所有其他项目之前都是yieled).我们现在展开Go(2)
:
Go(3):
Go(2):
foreach(var element in Go(1)):
yield return element;
yield return 2;
yield return 3;
Run Code Online (Sandbox Code Playgroud)
Go(1)
:
Go(3):
Go(2):
Go(1):
foreach(var element in Go(0))
yield return element;
yield return 1;
yield return 2;
yield return 3;
Run Code Online (Sandbox Code Playgroud)
如您所见,结果相对于调用被"向后"链接:
Go(3) --> Go(2) --> Go(1) --> Go(0) --> 0 --> 1 --> 2 --> 3
Run Code Online (Sandbox Code Playgroud)
我怀疑它会有什么不同 - 因为yield
我看到的唯一具体是yield 0
我想你想要这样的东西:
IEnumerable<int> Go(int b)
{
if (b > 0)
{
foreach (var element in Go(b-1))
{
yield return element;
}
}
yield return b;
}
Run Code Online (Sandbox Code Playgroud)
但这仍然是非常低效的,并将用更大的b
s 吹掉堆栈
对于你的问题:
你的代码:
会这样做:
b=3:
is b == 0? no ok, then enumerate and return everything from b=2...
b=2:
is b == 0? no ok, then enumerate and return everything from b=1...
b=1:
is b == 0? no ok, then enumerate everything from b=0...
b=0:
is b == 0? **YES** so yield a single **0**
everything was {0}
everything was {0}
everything was {0}
return is {0}
Run Code Online (Sandbox Code Playgroud)
另一种有条件的变体b==0
static IEnumerable<int> Go(int b)
{
if (b == 0)
{
yield return 0; //return 0 if b==0;
yield break; // say that iteration end;
}
foreach (var el in Go(b - 1))
{
yield return el;
}
yield return b; //return current b as element of result collection
}
Run Code Online (Sandbox Code Playgroud)
或没有yield break
static IEnumerable<int> Go(int b)
{
if (b == 0)
{
yield return 0;
}
else
{
foreach (var el in Go(b - 1))
{
yield return el;
}
yield return b; //return current b as element of result collection
}
}
Run Code Online (Sandbox Code Playgroud)