2

C# 2.0 で IEnumerable (および ICollection) を実装するカスタム コレクション クラスでアイテムをチャンクアップしようとしています。たとえば、一度に 1000 個のアイテムしか必要とせず、コレクションに 3005 個のアイテムがあるとします。以下に示す実用的な解決策がありますが、これは非常に原始的であるため、これを行うためのより良い方法が必要であると考えています。

これが私が持っているものです(たとえば、C#3.0のEnumerableとvarを使用しています。これらの参照を心の中でカスタムクラスに置き換えてください):

var items = Enumerable.Range(0, 3005).ToList();
int count = items.Count();
int currentCount = 0, limit = 0, iteration = 1;

List<int> temp = new List<int>();

while (currentCount < count)
{
    limit = count - currentCount;

    if (limit > 1000)
    {
        limit = 1000 * iteration;
    }
    else
    {
        limit += 1000 * (iteration - 1);
    }
    for (int i = currentCount; i < limit; i++)
    {
        temp.Add(items[i]);
    }

    //do something with temp

    currentCount += temp.Count;
    iteration++;
    temp.Clear();
}

C# 2.0 でこれを行うよりエレガントな方法を提案できる人はいますか? このプロジェクトが過去 5 年間のものであるかどうかは、Linq を使用できることを知っています (ここここで示されているように)。私の方法が機能することはわかっていますが、私の名前がそのような醜い (私の意見では) コードに関連付けられることは望ましくありません。

ありがとう。

4

2 に答える 2

8

まず。yieldはあなたの友達です。これは 2.0 で導入されました。検討:

public static IEnumerable<List<T>> Chunk<T>(IEnumerable<T> source, int chunkSize)
{
  List<T> list = new List<T>(chunkSize);
  foreach(T item in source)
  {
    list.Add(item);
    if(list.Count == chunkSize)
    {
      yield return list;
      list = new List<T>(chunkSize);
    }
  }
  //don't forget the last one!
  if(list.Count != 0)
    yield return list;
}

次に、タイプとサイズが柔軟であるため、うまく再利用できます。2.0 に制限されているということは、それを拡張メソッドにすることができないということだけです。

于 2012-08-29T21:12:12.670 に答える
2

これにはいくつかの方法があります。

各アイテムをそれが属するチャンクのインデックスに関連付けるだけの場合:

int processed = 0;
foreach (int item in items)
{
    int chunkIndex = processed++ / CHUNK_SIZE;
    ProcessItem(item, chunkIndex);
}

アイテムをバッチで処理したいが、チャンク コレクション全体を一度に必要としない場合:

int processed = 0, count = items.Count;
List<int> chunk = new List<int>(CHUNK_SIZE);
foreach (int item in items)
{
    chunk.Add(item);
    if (++processed % CHUNK_SIZE == 0 || processed == count) {
        ProcessChunk(chunk);
        chunk.Clear();
    }
}

リストのリストとしてすべてのチャンクを持ちたい場合:

int processed = 0, count = items.Count;
List<List<int>> chunks = new List<List<int>>();
foreach (int item in items)
{
    int chunkIndex = processed++ / CHUNK_SIZE;
    if (chunks.Count == chunkIndex) {
        chunks.Add(new List<int>(CHUNK_SIZE));
    }

    chunks[chunkIndex].Add(item);
}
于 2012-08-29T21:07:28.230 に答える