Robert McKee - 1 year ago 80
C# Question

# Make (mostly) equal length sets

Using LINQ (or morelinq), How do I divide an unknown length (but small) array into even sets with the smaller (uneven) sets at the end, but maintaining the order within each list?

```var array = new int[] {1,2,3,4}; var sets = array.something(3); ```

Looking for a result of:
`{1,2},{3},{4}`

``````{1} -> {1},{},{}
{1,2} -> {1},{2},{}
{1,2,3} -> {1},{2},{3}
{1,2,3,4} -> {1,2},{3},{4}
{1,2,3,4,5} -> {1,2},{3,4},{5}
{1,2,3,4,5,6} -> {1,2},{3,4},{5,6}
``````

My original code:

``````const int MaxPerColumn = 6;
var perColumn = (list.Count + columnCount - 1) / columnCount;
for (var col = 1; col <= columnCount; col++)
{
var items = list.Skip((col - 1) * columnCount).Take(perColumn).Pad(MaxPerColumn, "").ToList();

// DoSomething
}
``````

which did not work, because with a list of
`{1,2,3,4}`
it created
`{1,2},{3,4},{}`

I suggest not using Linq here, but `IEnumerator<T>`, not even `IEnumerable<T>` in the implementation:

``````public static IEnumerable<T[]> Something<T>(this IEnumerable<T> source, int count) {
if (null == source)
throw new ArgumentNullException("source");
else if (count <= 0)
throw new ArgumentOutOfRangeException("count");

int c = source.Count();
int size = c / count + (c % count > 0 ? 1 : 0);
int large = count - count * size + c;

using (var en = source.GetEnumerator()) {
for (int i = 0; i < count; ++i) {
T[] chunk = new T[i < large ? size : size - 1];

for (int j = 0; j < chunk.Length; ++j) {
en.MoveNext();

chunk[j] = en.Current;
}

yield return chunk;
}
}
}
``````

....

``````var array = new int[] { 1, 2, 3, 4 };

string result = string.Join(", ", array
.Something(5)
.Select(item => \$"[{string.Join(", ", item)}]"));

// [1], [2], [3], [4], []
Console.Write(result);
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download