I have a sorted List
of int
s (in descending order) that I need to re-order so that each batch (e.g. in 20s) has int
s that are as far apart as possible from each other.
So, for example, if the list contains the following bookings:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
and I was to process them in a batch of 4, would a good approach be to split the bookings into 4 lists (12 / 3) and moving down each list of 4 take 1 from each and append to the newly created re-ordered list? So, the new list would contain the bookings in the following order:
- 1
- 5
- 9
- 2
- 6
- 10
- 3
- 7
- 11
- 4
- 8
- 12
I appreciate it's not easy to understand what I'm after with my question so it might be easier to look at my code! I came up with the following approach and was wondering if it is the best/most performant way of achieving what I'm after:
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;
The Background (if you really want to know)
My problem is that I'm processing* a List
of int
s (bookings that are imported from a csv file and ordered) in parallel batches (of 20, say) and the closer together (more consecutive) these bookings are in the list the more likely it is that an exception will be thrown (beyond my control).
It's a tradeoff between running thousands of bookings synchronously (so no exception will be thrown) or running 20-odd in parallel with a likelihood of the said exception being thrown every once in a while. I've opted for the latter approach because it's quicker and any bookings that result in exceptions can be run synchronously after the async tasks have completed.
*calling a couple of services, passing in each booking int
in turn