1

100個の要素を持つコレクションがあるとしましょう。通常の列挙子は、これらの100個の要素を反復処理します。

スコープが「hehe」から「there」までの列挙子(通常の列挙子に基づく、つまり各コレクションごとではなく、1つの一般的なアプローチ)を作成したいと思います。たとえば、反復することができます。真ん中だけに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.1。

「そこ」に到達するには非常に時間がかかる可能性があるため、「そこ」からではなく「ここ」からイテレータが必要です。ただし、これは実際には些細なことですが、最も問題となるのはリセット方法です。

2.2。

ジョンは背景について尋ねました。私が実際に達成しようとしているのは、コレクションをスライスすることです(つまり、10個の文字列のコレクションがありますが、5つの要素のコレクションとして解釈し、各要素は2つの文字列のコレクションです)。ナイーブアルゴリズムは非常に単純ですが、非常に非効率的でもあります。コレクション〜16MB(文字列のリスト)を使用して、別のアプローチについて考えました。データをコピーせずに、単に再解釈します。したがって、コレクション全体からすべてのSIZE_OF_SLICE要素を選択する1つのイテレーターを作成します。また、最初のイテレーターから開始してSIZE_OF_SLICE要素に移動するこのスコープ付きイテレーターを作成します。

このようにして、データはその場で再利用されます。唯一の違いは、データを反復処理する方法です。スライスには十分で、高速である必要があります。

3

IListに効率的なスライスを実装しました(インデクサーがあると仮定すると、それは簡単です)が、気がかりです。リスト(LinkedList)と配列(List)の両方に一般的な効率的なアルゴリズムを提供することはできません(?)。したがって、これを読んでいて、その方法がわかっている場合は、10年経っても遠慮なく答えてください(C#がまだ残っていると仮定します)。

4

2 に答える 2

2

要素10〜30のみを表示するイテレータを取得するには、を使用しますが、original.Skip(10).Take(20)使用できるとは思いませんReset

リセットできるようにする必要がある場合は、次のようなものを使用してください

original.Skip(10).Take(20).ToArray()
于 2011-07-28T05:18:13.143 に答える
2

最小限の労力でこれを行うには、基本的に、イテレータをサポートする(たとえば)コレクションにデータを入力し、それを返します。ResetList<T>

それを怠惰に行うのは少し難しいです-つまり、初めて反復するときは、コレクションにデータを入力します。最初のリセット後、「再生」モードに入ります。私はそれが実行可能であると確信しています-それはほんの少しトリッキーでしょう。

(たとえば)15要素の後で最初にリセットすることをサポートする必要がある場合はさらに注意が必要です。その後、2回目に16番目の要素をヒットすると、元のイテレータに戻ります。うわぁ。

自分が持っている要件を正確に把握できれば、実装するのは楽しいことかもしれませんが...

編集:コメントの一部をこの回答に取り込むために:イテレータがリセットをサポートする保証がまったくないため、データをコピーせずにこれを行うことは一般的にできません。イテレータが乱数ジェネレータからのデータを提供している場合、またはそれが記録されていないライブブロードキャストである場合を想像してください。明らかにデータを再生するには、何かがそれをコピーする必要があります。

特定のソース実装を念頭に置いている場合、それは異なる可能性がありますが、インターフェイスだけでそれを行うことはできません。IEnumerator<T>

于 2011-07-28T05:25:38.940 に答える