c# - 如何创建范围有限的子枚举器?

标签 c# ienumerator

假设我有一个包含 100 个元素的集合。常规枚举器将迭代这 100 个元素。

我想创建枚举器(它基于常规枚举器,即它不是针对每个集合,而是一种通用方法),范围从“呵呵”到“那里”——我可以例如,仅在中间迭代 20 多个元素。

void foo(IEnumerable<int> coll)
{
   var regular_iter = coll.GetEnumerator();
   regular_iter.MoveNext();
   regular_iter.MoveNext();
   // ... 8 more
   var scoped_iter = new ScopeEnumerator(regular_iterator,20);

所以在这种情况下,当我调用“scoped_iter.Reset()”时,它被重置为它的 0 元素(整个集合的第 10 个元素)。

而且它也只“看到”10-30 的元素。

问题是 -- 如何实现这样的枚举器?

编辑

1.

我需要“这里”而不是“那里”的迭代器,因为到达“那里”可能非常耗时。然而这真的是小事,最有问题的是 Reset 方法。

2.

Jon 询问了背景。我真正想要实现的是对集合进行切片(即你有——比方说——10 个字符串的集合,但你想将其解释为 5 个元素的集合,每个元素都是 2 个字符串的集合)。朴素算法非常简单,但效率也很低。对于集合 ~16MB(字符串列表),我想到了另一种方法——简单地重新解释数据,而不复制它。因此,我会创建一个迭代器,它从整个集合中挑选每个 SIZE_OF_SLICE 元素,而且我会创建这个作用域迭代器,它会从第一个迭代器开始,然后去寻找 SIZE_OF_SLICE 元素。

这种方式将在适当的位置重新使用数据,唯一的区别是你如何迭代它。切片就足够了,而且速度应该很快。

3

我为 IList 实现了有效的切片(一旦你假设你有索引器,它就是小菜一碟)但它让我感到不安,你不能(?)为列表(LinkedList)和数组(List)提供通用的有效算法。因此,如果您正在阅读本文,并且知道如何去做,请不要犹豫回答,即使在 10 年后(假设 C# 仍与我们同在)。

最佳答案

要以最少的努力做到这一点,您基本上需要填充一个确实支持Reset的集合。 (例如 List<T> )与迭代器,然后返回它。

懒惰地这样做稍微有点棘手 - 即,第一次迭代时,填充一个集合。第一次重置后,进入“重播”模式。我确信这是可行的 - 只是有点棘手。

如果您必须支持第一次仅在(比如)15 个元素后重置,然后在第二次命中第 16 个元素时返回到原始迭代器,那将更加棘手。哎呀。

如果您可以准确地确定您的需求,那么实现起来可能会很有趣...

编辑:只是为了将一些评论纳入此答案:如果不复制数据,通常您不能这样做,因为根本无法保证迭代器将支持重置。想象一下,如果迭代器正在提供来自某个随机数生成器的数据,或者它是一个未被记录的直播 - 显然要重播数据,某些东西必须复制它。

如果您有一个特定的源实现,那可能会有所不同 - 但您不能通过 IEnumerator<T> 来实现界面。

关于c# - 如何创建范围有限的子枚举器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6854390/

相关文章:

c# - 改DBML,如何改SQL数据库?

c# - 直接添加引用和通过Nuget添加包有什么区别

c# - 使用 MsBuild 时 Wix 的构建顺序不正确

c# - Webservice 需要 Byte[] - 我如何从 PHP 发送它?

c# - 从 IEnumerable 转换为 IEnumerator

c# - 使用协程淡入/淡出 TextMeshPro 文本元素

c# - 迭代和修改字典

c# - Silverlight 和非 UI 线程中的回调

F#:向下转换 seq 到 IEnumerator

c# - Dispose 与 Iterator block