C# 无显式枚举数的递归生成器
下面是一个使用显式枚举数的生成器:C# 无显式枚举数的递归生成器,c#,generator,yield-return,ienumerator,C#,Generator,Yield Return,Ienumerator,下面是一个使用显式枚举数的生成器: static IEnumerable<string> generate(string s) { yield return new Regex("e").Replace(s, "", 1); yield return new Regex("aaaa").Replace(s, "e", 1); yield return new Regex("aa").Replace(s, "bb", 1); yield return
static IEnumerable<string> generate(string s)
{
yield return new Regex("e").Replace(s, "", 1);
yield return new Regex("aaaa").Replace(s, "e", 1);
yield return new Regex("aa").Replace(s, "bb", 1);
yield return new Regex("ba").Replace(s, "abbb", 1);
yield return new Regex("bb").Replace(s, "aa", 1);
var en0 = generate(new Regex("e").Replace(s, "", 1)).GetEnumerator();
var en1 = generate(new Regex("aaaa").Replace(s, "e", 1)).GetEnumerator();
var en2 = generate(new Regex("aa").Replace(s, "bb", 1)).GetEnumerator();
var en3 = generate(new Regex("ba").Replace(s, "abbb", 1)).GetEnumerator();
var en4 = generate(new Regex("bb").Replace(s, "aa", 1)).GetEnumerator();
while(true)
{
en0.MoveNext(); yield return en0.Current;
en1.MoveNext(); yield return en1.Current;
en2.MoveNext(); yield return en2.Current;
en3.MoveNext(); yield return en3.Current;
en4.MoveNext(); yield return en4.Current;
}
}
显示表格:
在上面的评论中,Rob提到一种方法是使用
Zip
下面是使用Zip
生成的一个版本:
static IEnumerable<string> generate(string s)
{
yield return new Regex("e").Replace(s, "", 1);
yield return new Regex("aaaa").Replace(s, "e", 1);
yield return new Regex("aa").Replace(s, "bb", 1);
yield return new Regex("ba").Replace(s, "abbb", 1);
yield return new Regex("bb").Replace(s, "aa", 1);
var seq =
generate(new Regex("e").Replace(s, "", 1))
.Zip(generate(new Regex("aaaa").Replace(s, "e", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b })
.Zip(generate(new Regex("aa").Replace(s, "bb", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b })
.Zip(generate(new Regex("ba").Replace(s, "abbb", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b })
.Zip(generate(new Regex("bb").Replace(s, "aa", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b });
foreach (var elt in seq) yield return elt;
}
静态IEnumerable生成(字符串s)
{
收益率返回新的正则表达式(“e”)。替换为“,”,1);
收益率回报新正则表达式(“aaaa”)。替换(s,“e”,1);
收益率回报新的正则表达式(“aa”)。替换(s,“bb”,1);
收益率回报新的正则表达式(“ba”)。替换“缩写”,1);
收益率回报新的正则表达式(“bb”)。替换(s,“aa”,1);
var-seq=
生成(新正则表达式(“e”)。替换(s,“,1))
.Zip(generate(new Regex(“aaaa”).Replace(s,“e”,1)),(a,b)=>new{a=a,b=b})。SelectMany(elt=>new[]{elt.a,elt.b})
.Zip(generate(new Regex(“aa”).Replace(s,“bb”,1)),(a,b)=>new{a=a,b=b})。SelectMany(elt=>new[]{elt.a,elt.b})
.Zip(generate(new Regex(“ba”).Replace(s,“abbb”,1)),(a,b)=>new{a=a,b=b}.SelectMany(elt=>new[]{elt.a,elt.b})
.Zip(generate(new Regex(“bb”).Replace(s,“aa”,1)),(a,b)=>new{a=a,b=b});
foreach(var elt,见下文)收益率收益率elt;
}
Eric Lippert在上面提到的帖子中包含了一个ZipMany
函数。以下是使用ZipMany
生成的一个版本:
static IEnumerable<string> generate(string s)
{
yield return new Regex("e").Replace(s, "", 1);
yield return new Regex("aaaa").Replace(s, "e", 1);
yield return new Regex("aa").Replace(s, "bb", 1);
yield return new Regex("ba").Replace(s, "abbb", 1);
yield return new Regex("bb").Replace(s, "aa", 1);
var seq =
ZipMany(new[]
{
generate(new Regex("e").Replace(s, "", 1)),
generate(new Regex("aaaa").Replace(s, "e", 1)),
generate(new Regex("aa").Replace(s, "bb", 1)),
generate(new Regex("ba").Replace(s, "abbb", 1)),
generate(new Regex("bb").Replace(s, "aa", 1))
},
elts => elts).SelectMany(items => items);
foreach (var elt in seq) yield return elt;
}
静态IEnumerable生成(字符串s)
{
收益率返回新的正则表达式(“e”)。替换为“,”,1);
收益率回报新正则表达式(“aaaa”)。替换(s,“e”,1);
收益率回报新的正则表达式(“aa”)。替换(s,“bb”,1);
收益率回报新的正则表达式(“ba”)。替换“缩写”,1);
收益率回报新的正则表达式(“bb”)。替换(s,“aa”,1);
var-seq=
ZipMany(新[]
{
生成(新正则表达式(“e”)。替换(s,“,1”),
生成(新正则表达式(“aaaa”)。替换(s,“e”,1)),
生成(新正则表达式(“aa”)。替换(s,“bb”,1)),
生成(新正则表达式(“ba”)。替换(s,“abbb”,1)),
生成(新正则表达式(“bb”)。替换(s,“aa”,1))
},
elts=>elts)。选择多个(项目=>items);
foreach(var elt,见下文)收益率收益率elt;
}
您可以使用Zip
,因为您假设en*
序列具有相同的长度hey@Rob。我知道您可以压缩两个IEnumerables:generate(…).zip(generate(…),selector
。但是不清楚指定什么作为selector
。选择器为序列中的每一对创建一个新对象,因此您可能会有类似a.zip(b,(左,右)=>new{a=left,b=right}
它将[1,2,3]
[4,5,6]
转换为[{a=1,b=4},{a=2,b=5},{a=3,b=6}]
是的-那就好了。在上面的示例中,您可以循环通过zip:foreach(zip中的var对){yield return pair pair.a;yield return pair pair.b;}
澄清一下:有时使用枚举器是不可避免的;有时确实需要对序列的枚举方式进行细粒度控制。但我的首选是构建一个使用枚举器的更高级别的序列操作,如ZipMany
,然后将更高级别的操作应用于您的问题。请尝试保持mechanism代码和业务代码是分开的。SelectMany()
将按不正确的顺序对>2
序列进行展平。它将生成[a1,b1,c1,a2,b2,c2]
,而不是[a1,c1,b1,c2]
。此外,一旦其中一个序列完成,zip将结束。这里,c将首先完成(因为它的发射速度是原来的两倍)并且你会丢失a
和b
中的项目。序列越多,效果越差。@对于这个特定的应用程序,元素的顺序无关紧要。而且,每个子序列都是无限的,因此没有一个子序列会在另一个子序列之前完成。
static IEnumerable<string> generate(string s)
{
yield return new Regex("e").Replace(s, "", 1);
yield return new Regex("aaaa").Replace(s, "e", 1);
yield return new Regex("aa").Replace(s, "bb", 1);
yield return new Regex("ba").Replace(s, "abbb", 1);
yield return new Regex("bb").Replace(s, "aa", 1);
var seq =
ZipMany(new[]
{
generate(new Regex("e").Replace(s, "", 1)),
generate(new Regex("aaaa").Replace(s, "e", 1)),
generate(new Regex("aa").Replace(s, "bb", 1)),
generate(new Regex("ba").Replace(s, "abbb", 1)),
generate(new Regex("bb").Replace(s, "aa", 1))
},
elts => elts).SelectMany(items => items);
foreach (var elt in seq) yield return elt;
}