2

各バッチ (たとえば 20 秒) が互いにできるだけ離れた sを持つように並べ替える必要Listがあるints の並べ替え (降順) があります。int

たとえば、リストに次の予約が含まれているとします。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

そして、私はそれらを4つのバッチで処理することになりました。予約を4つのリスト(12 / 3)に分割し、4つの各リストを下に移動して、それぞれから1つを取得し、新しく作成された並べ替えられたリストに追加するのが良い方法でしょうか? したがって、新しいリストには次の順序で予約が含まれます。

  • 1
  • 5
  • 9
  • 2
  • 6
  • 10
  • 3
  • 7
  • 11
  • 4
  • 8
  • 12

私の質問で何を求めているのかを理解するのは簡単ではないので、私のコードを見る方が簡単かもしれません! 私は次のアプローチを思いつきましたが、それが私が求めているものを達成するための最良/最もパフォーマンスの高い方法であるかどうか疑問に思っていました:

var bookings = new List<int>();

// <snip>import bookings ints from csv file into bookings list</snip>

bookings = bookings.Distinct().OrderByDescending(x => x).ToList();

int chunkSize = 20;

// get number of chunks/batches
int chunkCount = (int)Math.Ceiling((double)bookings.Count/(double)chunkSize);

// split booking list into number of chunks
// add the ith booking from each chunk into new list
// ToChunks() extension method from http://stackoverflow.com/a/6852288/1578713
var chunkList = bookings.ToChunks(chunkCount).ToList();
var reorderedBookings = new List<int>();
for (int i=0; i<chunkCount; i++)
{
    // last chunk may be smaller than chunkSize hence the check
    reorderedBookings.AddRange(from chunk in chunkList where chunk.Count() > i 
        select chunk.ToList()[i]);
}

bookings = reorderedBookings;

背景(本当に知りたい場合)

私の問題は、(csv ファイルからインポートされて注文された予約) を並列バッチ (たとえば 20 個) でList処理している*ことです。int例外がスローされるということです(私の制御を超えて)。

これは、何千もの予約を同期的に実行する (例外はスローされません) か、20 奇数を並行して実行するかのトレードオフであり、前述の例外が時々スローされる可能性があります。私は後者のアプローチを選択しました。これは、非同期タスクが完了した後、例外が発生する予約を同期的に実行できるため、より高速だからです。

*いくつかのサービスを呼び出し、各予約intを順番に渡す

4

2 に答える 2

1

Servyがあなたが望むものについて正しいと仮定すると、あなたはどちらかとしてそれを行うことができます

int i = 0;
var grouped = bookings.OrderBy(x => (i++) % chunkSize);

また

int i = 0;
var grouped = bookings.GroupBy(x => (i++) % chunkSize);

1つ目は単一のリストを提供し、2つ目はそれを個別のリストに分割します。

于 2012-11-28T18:30:07.277 に答える
1

さて、それはかなり簡単です:

public static IEnumerable<IEnumerable<T>> BatchAndSeparate<T>(IList<T> source, int batchSize)
{
    int numBatches = (int)Math.Ceiling(source.Count / (double)batchSize);

    for (int i = 0; i < numBatches; i++)
    {
        var buffer = new List<T>();
        for (int j = i; j < source.Count; j += numBatches)
        {
            buffer.Add(source[j]);
        }
        yield return buffer;
    }
}

一般的なアルゴリズムは、バッチごとに、インデックスがそのバッチの番号 (ゼロのインデックス) で始まり、反復ごとにバッチの数を追加することです。

次のように使用できます。

var batches = BatchAndSeparate(Enumerable.Range(1, 13).ToList(), 3);

foreach (var batch in batches)
{
    Console.WriteLine(string.Join(" ", batch));
}

これは印刷されます:

1 6 11
2 7 12
3 8 13
4 9
5 10

このように表示されると、それが正しいことが簡単にわかります。各列を下に移動し、数字が 1 ずつ増加することを確認してから、一番左の列から右に移動します。

于 2012-11-28T18:24:40.057 に答える