我有一个List
int
的{{1}} s(按降序排列)我需要重新排序,这样每个批次(例如20s)都有int
s,如同尽可能远离彼此。
因此,例如,如果列表包含以下预订:
我将以4批次处理它们,一个好方法是将预订分成4个列表(12/3)并向下移动每个4个列表中的每个列表并附加到新创建的列表中订购清单?因此,新列表将按以下顺序包含预订:
我很欣赏我的问题并不容易理解,因此查看我的代码可能更容易!我提出了以下方法,并想知道它是否是实现我所追求的最好/最高效的方式:
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;
我的问题是我正在处理List
int
个int
(从csv文件导入并订购的预订)并行批次(比如说20个)和更接近的(更连续)这些预订在列表中,更有可能抛出异常(超出我的控制范围)。
这是在同步运行数千个预订(因此不会抛出异常)或并行运行20多个之间的权衡,并且偶尔会抛出所述异常的可能性。我选择了后一种方法,因为它更快,任何导致异常的预订都可以在异步任务完成后同步运行。
*拨打几项服务,依次传递每个预订{{1}}
答案 0 :(得分: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,然后从最左边的列向右移动。
答案 1 :(得分:1)
假设Servy对你想要的是正确的,你可以这样做
int i = 0;
var grouped = bookings.OrderBy(x => (i++) % chunkSize);
或
int i = 0;
var grouped = bookings.GroupBy(x => (i++) % chunkSize);
第一个会给你一个列表,第二个会把它分成单独的列表。