繁体   English   中英

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

[英]How to create sub-enumerator with limited scope?

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

我想创建枚举器(它基于常规枚举器,即它不是每个集合,而是一个,一般方法),其范围从“hehe”到“there” - 我可以例如迭代仅中间超过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。

我需要来自“here”的迭代器,而不是“那里”,因为进入“那里”可能非常耗时。 然而,这实际上是次要的,最有问题的是Reset方法。

2。

乔恩询问了背景。 我真正想要实现的是切片集合(即你有 - 比方说 - 10个字符串的集合,但你想把它解释为5个元素的集合,每个元素是2个字符串的集合)。 朴素算法非常简单,但效率也很低。 收集~16MB(字符串列表)我虽然有另一种方法 - 只需重新解释数据,而不复制它。 所以我会创建一个迭代器,从整个集合中选择每个SIZE_OF_SLICE元素,我也会创建这个作用域迭代器,它将从第一个迭代器开始,然后转到SIZE_OF_SLICE元素。

这样就可以重新使用数据,唯一的区别就是你如何迭代数据。 切片就足够了,它应该很快。

3

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

要获得只能看到元素10-30的迭代器,请使用original.Skip(10).Take(20) ,尽管我认为你不能使用Reset

如果你需要能够重置它,只需使用类似的东西

original.Skip(10).Take(20).ToArray()

为了用最小的努力做到这一点,你基本上填充的集合,其支持Reset (如List<T>与迭代器,然后返回。

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

如果你不得不支持仅在(比方说)15个元素之后第一次重置,那么当你第二次击中第16个元素,返回到原始迭代器时,这将更加棘手。 让人惊讶。

如果你可以确切地确定你的要求,那么实施它可能是一件有趣的事情......

编辑:只是将一些注释写入这个答案: 一般情况下,如果不复制数据,就不能这样做,因为不能保证迭代器完全支持重置。 试想一下,如果迭代器是由一些随机数发生器提供的数据,或者是一个未被记录直播-显然重播数据, 有事必须将其复制。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM