4

Process(IEnumerable<Record> records)私は、一度に 3 つまでのレコードを処理できるメソッドを持っています。何百ものレコードがあるので、グループで渡す必要があります。私はこれをします:

var _Records = Enumerable.Range(1, 16).ToArray();
for (int i = 0; i < int.MaxValue; i += 3)
{
    var _ShortList = _Records.Skip(i).Take(3);
    if (!_ShortList.Any())
        break;
    Process(_ShortList);
}
// TODO: finish

それはうまくいきますが...もっと良い方法はありますか?

4

8 に答える 8

4

MoreLinqを使用できますBatch

var result=Enumerable.Range(1, 16).Batch(3);

また

var arrayOfArrays = Enumerable.Range(1, 16).Batch(3).Select(x => x.ToArray()).ToArray();

そして、もしあなたがそれを見たいなら、ここにソースがあります。

于 2012-06-14T15:46:48.283 に答える
1

これを行う別の LINQ-y の方法を次に示します。

var batchSize = 3;
Enumerable.Range(0, (_Records.Length - 1)/batchSize + 1)
    .ToList()
    .ForEach(i => Process(_Records.Skip(i * batchSize).Take(batchSize)));
于 2012-06-14T16:18:08.453 に答える
1

次の拡張メソッドを使用できます。

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int chunkSize)
{
    return source
        .Select((value, i) => new { Index = i, Value = value })
        .GroupBy(item => item.Index % chunkSize)
        .Select(chunk => chunk.Select(item => item.Value));
}

アイテムのソース コレクションを、指定されたサイズの複数のチャンクに分割します。したがって、コードは次のようになります。

foreach (var chunk in Enumerable.Range(1, 16).Split(3))
{
    Process(chunk);
}
于 2012-06-14T16:02:39.037 に答える
0

独自の拡張メソッドを作成できます。

static class Extensions {

  public static IEnumerable<IEnumerable<T>> ToBlocks<T>(this IEnumerable<T> source, int blockSize) {
    var count = 0;
    T[] block = null;
    foreach (var item in source) {
      if (block == null)
        block = new T[blockSize];
      block[count++] = item;
      if (count == blockSize) {
        yield return block;
        block = null;
        count = 0;
      }
    }
    if (count > 0)
      yield return block.Take(count);
  }

}
于 2012-06-14T16:13:21.627 に答える
0
var _Records = Enumerable.Range(1, 16).ToArray();

int index = 0;
foreach (var group in _Records.GroupBy(element => index++ / 3))
    Process(group);

注:上記のコードは短く、比較的効率的ですが、それでも可能な限り効率的ではありません(基本的に、バックグラウンドでハッシュテーブルを構築します)。もう少し面倒ですが、より高速な方法は次のようになります。

var _Records = Enumerable.Range(1, 16).ToArray();

var buff = new int[3];
int index = 0;

foreach (var element in _Records) {
    if (index == buff.Length) {
        Process(buff);
        index = 0;
    }
    buff[index++] = element;
}

if (index > 0)
    Process(buff.Take(index));

または、より再利用可能な形式にパックします。

public static class EnumerableEx {

    public static void Paginate<T>(this IEnumerable<T> elements, int page_size, Action<IEnumerable<T>> process_page) {

        var buff = new T[3];
        int index = 0;
        foreach (var element in elements) {
            if (index == buff.Length) {
                process_page(buff);
                index = 0;
            }
            buff[index++] = element;
        }

        if (index > 0)
            process_page(buff.Take(index));

    }

}

// ...

var _Records = Enumerable.Range(1, 16).ToArray();
_Records.Paginate(3, Process);
于 2012-06-14T16:11:52.827 に答える
0
public static void ChunkProcess<T>(IEnumerable<T> source, int size, Action<IEnumerable<T>> action)
{
    var chunk = source.Take(size);

    while (chunk.Any())
    {
        action(chunk);

        source = source.Skip(size);
        chunk = source.Take(size);
    }
}

そしてあなたのコードは

ChunkProcess(_Records, 3, Process);
于 2012-06-14T16:28:48.730 に答える
0

ソリューションで「ページネーション」が複数回必要な場合は、拡張メソッドの使用を検討してください。

LINQPad で一緒にハッキングすると、うまくいきます。

public static class MyExtensions {
    public static IEnumerable<IEnumerable<T>> Paginate<T>(this IEnumerable<T> source, int pageSize) {
        T[] buffer = new T[pageSize];
        int index = 0;

        foreach (var item in source) {
            buffer[index++] = item;

            if (index >= pageSize) {
                yield return buffer.Take(pageSize);
                index = 0;
            }
        }

        if (index > 0) {
            yield return buffer.Take(index);
        }
    }
}

基本的に、サイズのバッファーを事前に満たし、いっぱいにpageSizeなったときにそれを生成します。< pageSize要素が残っている場合は、それらも生成します。そう、

Enumerable.Range(1, 10).Paginate(3).Dump(); // Dump is a LINQPad extension

譲ります

{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10}}
于 2012-06-14T16:04:40.987 に答える
0

この拡張メソッドは正しく機能しています。

public static class EnumerableExtentions
{
    public static IEnumerable<IEnumerable<T>> Chunks<T>(this IEnumerable<T> items, int   size)
    {
        return
            items.Select((member, index) => new { Index = index, Value = member })
                .GroupBy(item => (int)item.Index / size)
                .Select(chunk => chunk.Select(item => item.Value));
    }
}
于 2014-08-19T00:54:41.407 に答える