【发布时间】:2017-10-25 14:33:46
【问题描述】:
这是一个使用显式枚举器的生成器:
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;
}
}
在this answer 中,Eric Lippert 建议不要使用枚举器。
有没有一种不用显式枚举器的好方法来表达上述内容?
上面的生成器是干什么用的?
在 Charles C. Pinter 的 A Book of Abstract Algebra 中,练习 5.F.3 指出:
让 G 是组 {e, a, b, b^2, b^3, ab ab^2, ab^3},其生成器满足 a^4 = e、a^2 = b^2、ba = ab^3。写出G的表格。 (G被称为四元组。)
以下程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace pinter_5.F._1
{
class Program
{
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;
}
}
static void Main(string[] args)
{
var G = new List<string>() { "e", "a", "b", "bb", "bbb", "ab", "abb", "abbb" };
foreach (var x in G)
{
foreach (var y in G)
{
var result = generate(x + y).First(elt => G.Contains(elt));
Console.Write($"{x,-5} {y,-5} = {result,-5} |");
}
Console.WriteLine();
}
}
}
}
显示表格:
【问题讨论】:
-
您可以使用
Zip,因为您假设en*序列的长度相同 -
嘿@Rob。我知道您可以像这样压缩两个 IEnumerable:
generate(...).Zip(generate(...), selector。但不清楚将什么指定为selector。 -
选择器为序列中的每一对创建一个新对象,因此您可能有类似
a.Zip(b, (left, right) => 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(var pair in zip) { yield return pair.a; yield return pair.b; } -
澄清:有时使用枚举器是不可避免的;有时您确实需要对序列的枚举方式进行细粒度控制。但我的偏好会是构建一个更高级别的序列操作——比如
ZipMany——它使用枚举器,然后将更高级别的操作应用于您的问题。尽量保持机制代码和业务代码分开。
标签: c# generator yield-return ienumerator