如何创建范围有限的子枚举器
本文关键字:枚举 范围 何创建 创建 | 更新日期: 2023-09-27 18:03:51
假设我有一个包含100个元素的集合。常规枚举器将遍历这100个元素。
我想创建枚举器(这是基于常规枚举器,即它不是每个集合,而是一个,一般方法),其范围是从"嘿嘿";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。
我需要迭代器from "here",而不是from "那里",因为要到达"那里"可能非常耗时。然而,这真的是一件小事,最有问题的是Reset方法。
2。
Jon询问了背景。我真正尝试实现的是切片集合(即,你有-让我们说- 10个字符串的集合,但你想把它解释为5个元素的集合,每个元素是2个字符串的集合)。朴素算法很简单,但效率也很低。对于collection ~16MB(字符串列表),我考虑了另一种方法——简单地重新解释数据,而不复制它。因此,我将创建一个迭代器,它将从整个集合中挑选所有SIZE_OF_SLICE元素,并且我还将创建这个范围迭代器,它将从第一个迭代器开始,并寻找SIZE_OF_SLICE元素。
这样数据将被就地重用,唯一的区别是如何迭代它。它足以用于切片,并且应该是快速的。
3
我为illist实现了高效的切片(一旦你假设你有索引器,这是小菜一碟),但它让我感到不安,你不能(?)为列表(LinkedList)和数组(list)提供通用的高效算法。因此,如果你正在阅读这篇文章,并且有一个想法如何做到这一点,不要犹豫回答,即使在10年后(假设c#仍将与我们同在)。
要以最小的努力做到这一点,你基本上应该用迭代器填充一个支持 Reset
(例如List<T>
)的集合,然后返回它。
使用惰性稍微有点棘手——即第一次迭代,填充一个集合。第一次重置后,进入"重放"模式。我相信这是可行的——只是有点棘手。
如果必须支持仅在(例如)15个元素之后第一次重置,然后在第二次迭代到第16个元素时返回到原始迭代器,这将更加棘手。呵。
如果你能准确地找出你的需求,那么实现它可能是一件有趣的事情…
编辑:只是把一些注释拉到这个答案中:如果不复制数据,一般情况下不能这样做,因为不能保证迭代器完全支持重置。想象一下,如果迭代器提供的数据来自某个随机数生成器,或者它是一个没有被记录的直播——显然,要重播数据,某些必须复制它。如果你有一个特定的源实现,这可能是不同的-但你不能通过仅仅通过 IEnumerator<T>
接口。
要获得只看到元素10-30的迭代器,请使用original.Skip(10).Take(20)
,尽管我认为您不能在其上使用Reset
。
如果你需要能够重置它,只需使用像
这样的东西original.Skip(10).Take(20).ToArray()