Reputation: 45253
I have a collection of items. I also have a dynamic number of columns that may change.
I need an algorithm that will redistribute my items into buckets such that I can bind them to the UI. I would like to fill down and then across, but in a manner that fills the width first.
I'd like the most even and 'rectangular' distribution as possible.
This arrangement is wrong since it doesn't fill column 9.
1 2 3 4 5 6 7 8 9
A D G J M P S V
B E H K N Q T
C F I L O R U
This arrangement is correct, though less desirable...
1 2 3 4 5 6 7 8 9
A D G J M P S U V
B E H K N Q T
C F I L O R
...than this one, which is visually more balanced.
1 2 3 4 5 6 7 8 9
A D G J M O Q S U
B E H K N P R T V
C F I L
Thanks. This is Q&A, I solved it already.
Upvotes: 3
Views: 846
Reputation: 45253
This will balance items across buckets with a 'left side bias'.
public static T[][] FillBucketsEvenly<T>(IEnumerable<T> items, int bucketCount)
{
int itemsPerBucket = items.Count() / bucketCount;
int countOfBucketsTakingExtraOne = items.Count() % bucketCount;
T[][] buckets = new T[bucketCount][];
// Build empty array structure.
for (int i = 0; i < bucketCount; i++)
{
if (i < countOfBucketsTakingExtraOne)
{
buckets[i] = new T[itemsPerBucket + 1];
}
else
{
buckets[i] = new T[itemsPerBucket];
}
}
// Fill the structure.
int itemsAdded = 0;
foreach(var bucket in buckets)
{
int grabSize = bucket.Count();
var grab = items.Skip(itemsAdded).Take(grabSize);
for (int i = 0; i < grabSize; i++)
{
bucket[i] = grab.ElementAt(i);
}
itemsAdded += grabSize;
}
return buckets;
}
Upvotes: 2