简体   繁体   English

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

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

Let's say I have collection with 100 elements. 假设我有100个元素的集合。 Regular enumerator would iterate over those 100 elements. 常规枚举器将迭代这100个元素。

I would like to create enumerator (which is based on the regular enumerator, ie it is not per each collection, but rather one, general approach) which scope is from "hehe" to "there" -- and I could have for example iterate over 20 elements in the middle only. 我想创建枚举器(它基于常规枚举器,即它不是每个集合,而是一个,一般方法),其范围从“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);

So in such case when I call "scoped_iter.Reset()" it is reseted to its 0 element (10th for entire collection). 所以在这种情况下,当我调用“scoped_iter.Reset()”时,它会重置为0元素(整个集合的第10个元素)。

And also it "sees" only elements from 10-30. 而且它“只看到”了10-30的元素。

The question is -- how to implement such enumerator? 问题是 - 如何实现这样的枚举器?

Edit 编辑

1. 1。

I need iterator from "here", not from "there", because getting to "there" could be very time consuming. 我需要来自“here”的迭代器,而不是“那里”,因为进入“那里”可能非常耗时。 However this is minor thing really, the most problematic is Reset method. 然而,这实际上是次要的,最有问题的是Reset方法。

2. 2。

Jon asked about the background. 乔恩询问了背景。 What I really try to achieve is slicing the collection (ie you have the -- let's say -- collection of 10 strings, but you would like to interpret it as collection of 5 elements, each element being collection of 2 strings). 我真正想要实现的是切片集合(即你有 - 比方说 - 10个字符串的集合,但你想把它解释为5个元素的集合,每个元素是2个字符串的集合)。 Naive algorithm is pretty simple, but also is very inefficient. 朴素算法非常简单,但效率也很低。 With collection ~16MB (list of strings) I though about another approach -- simply reinterpreting the data, without copying it. 收集~16MB(字符串列表)我虽然有另一种方法 - 只需重新解释数据,而不复制它。 So I would create one iterator which picks every SIZE_OF_SLICE element from entire collection, and also I would create this scoped iterator which would start from the first iterator and go for SIZE_OF_SLICE elements. 所以我会创建一个迭代器,从整个集合中选择每个SIZE_OF_SLICE元素,我也会创建这个作用域迭代器,它将从第一个迭代器开始,然后转到SIZE_OF_SLICE元素。

This way data will be re-used in place, the only difference would be how you iterate over it. 这样就可以重新使用数据,唯一的区别就是你如何迭代数据。 It is sufficient for slicing and it should be fast. 切片就足够了,它应该很快。

3 3

I implemented efficient slicing for IList (once you assume you have indexer, it is piece of cake) but it is disturbing me, you cannot (?) provide general efficient algorithm for both list (LinkedList) and arrays (List). 我为IList实现了有效的切片(一旦你假设你有索引器,它就是小菜一碟)但它让我感到不安,你不能(?)为列表(LinkedList)和数组(List)提供通用的高效算法。 So if you are reading this, and have an idea how to do it, do not hestitate to answer, even after 10 years (assuming C# will be still with us). 因此,如果您正在阅读本文并了解如何操作,请不要犹豫回答,即使在10年后(假设C#仍然在我们身边)。

To get an iterator that only sees elements 10-30, use original.Skip(10).Take(20) , although I don't think you can use Reset on it. 要获得只能看到元素10-30的迭代器,请使用original.Skip(10).Take(20) ,尽管我认为你不能使用Reset

If you need to be able to reset it, just use something like 如果你需要能够重置它,只需使用类似的东西

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

To do this with the minimum of effort, you'd basically populate a collection which does support Reset (eg List<T> ) with the iterator, and then return that. 为了用最小的努力做到这一点,你基本上填充的集合,其支持Reset (如List<T>与迭代器,然后返回。

It's slightly trickier to do that lazily - ie the first time you iterate, populate a collection. 懒惰地做这个有点棘手 - 即第一次迭代时,填充一个集合。 After the first reset, go into "replay" mode. 首次重置后,进入“重播”模式。 I'm sure it's feasible - it would just be slightly tricky. 我确信它是可行的 - 它只是有点棘手。

It would be even trickier if you had to support being reset the first time after only (say) 15 elements, then when you hit the 16th element the second time round, going back to the original iterator. 如果你不得不支持仅在(比方说)15个元素之后第一次重置,那么当你第二次击中第16个元素,返回到原始迭代器时,这将更加棘手。 Yikes. 让人惊讶。

If you can scope out exactly what requirements you have, it could be a fun thing to implement though... 如果你可以确切地确定你的要求,那么实施它可能是一件有趣的事情......

EDIT: Just to pull some of the comments into this answer: you can't do this in general without copying the data, because there's no guarantee that the iterator will support being reset at all. 编辑:只是将一些注释写入这个答案: 一般情况下,如果不复制数据,就不能这样做,因为不能保证迭代器完全支持重置。 Imagine if the iterator is providing data from some random number generator, or it's a live broadcast which isn't being recorded - obviously to replay the data, something would have to copy it. 试想一下,如果迭代器是由一些随机数发生器提供的数据,或者是一个未被记录直播-显然重播数据, 有事必须将其复制。

If you have a particular source implementation in mind, that may be different - but you can't do it through just the IEnumerator<T> interface. 如果你有一个特定的源实现 ,那可能会有所不同 - 但你不能通过IEnumerator<T>接口来实现。

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

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