score:56

Use the following extension method to break the input into subsets

``````public static class IEnumerableExtensions
{
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
List<T> toReturn = new List<T>(max);
foreach(var item in source)
{
if (toReturn.Count == max)
{
toReturn = new List<T>(max);
}
}
if (toReturn.Any())
{
}
}
}
``````

score:0

Take won't be very efficient, because it doesn't remove the entries taken.

why not use a simple loop:

``````public IEnumerable<IList<T>> Partition<T>(this/* <-- see extension methods*/ IEnumerable<T> src,int num)
{
IEnumerator<T> enu=src.getEnumerator();
while(true)
{
List<T> result=new List<T>(num);
for(int i=0;i<num;i++)
{
if(!enu.MoveNext())
{
if(i>0)yield return result;
yield break;
}
}
yield return result;
}
}
``````

score:0

``````from b in Enumerable.Range(0,8) select items.Where((x,i) => (i % 8) == b);
``````

score:0

The simplest solution is given by Mel:

``````public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
``````

Concise but slower. The above method splits an IEnumerable into chunks of desired fixed size with total number of chunks being unimportant. To split an IEnumerable into N number of chunks of equal sizes or close to equal sizes, you could do:

``````public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
``````

To speed up things, a straightforward approach would do:

``````public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
if (partitionSize <= 0)
throw new ArgumentOutOfRangeException("partitionSize");

int innerListCounter = 0;
int numberOfPackets = 0;
foreach (var item in items)
{
innerListCounter++;
if (innerListCounter == partitionSize)
{
yield return items.Skip(numberOfPackets * partitionSize).Take(partitionSize);
innerListCounter = 0;
numberOfPackets++;
}
}

if (innerListCounter > 0)
yield return items.Skip(numberOfPackets * partitionSize);
}
``````

This is faster than anything currently on planet now :) The equivalent methods for a `Split` operation here

score:3

It's not at all what the original Linq designers had in mind, but check out this misuse of GroupBy:

``````public static IEnumerable<IEnumerable<T>> BatchBy<T>(this IEnumerable<T> items, int batchSize)
{
var count = 0;
return items.GroupBy(x => (count++ / batchSize)).ToList();
}

[TestMethod]
public void BatchBy_breaks_a_list_into_chunks()
{
var values = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var batches = values.BatchBy(3);
batches.Count().ShouldEqual(4);
batches.First().Count().ShouldEqual(3);
batches.Last().Count().ShouldEqual(1);
}
``````

I think it wins the "golf" prize for this question. The `ToList` is very important since you want to make sure the grouping has actually been performed before you try doing anything with the output. If you remove the `ToList`, you will get some weird side effects.

score:15

You're better off using a library like MoreLinq, but if you really had to do this using "plain LINQ", you can use `GroupBy`:

``````var sequence = new[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

var result = sequence.Select((x, i) => new {Group = i/8, Value = x})
.GroupBy(item => item.Group, g => g.Value)
.Select(g => g.Where(x => true));

// result is: { {1,2,3,4,5,6,7,8}, {9,10,11,12,13,14,15,16} }
``````

Basically, we use the version of `Select()` that provides an index for the value being consumed, we divide the index by 8 to identify which group each value belongs to. Then we group the sequence by this grouping key. The last `Select` just reduces the `IGrouping<>` down to an `IEnumerable<IEnumerable<T>>` (and isn't strictly necessary since `IGrouping` is an `IEnumerable`).

It's easy enough to turn this into a reusable method by factoring our the constant `8` in the example, and replacing it with a specified parameter. It's not necessarily the most elegant solution, and it is not longer a lazy, streaming solution ... but it does work.

You could also write your own extension method using iterator blocks (`yield return`) which could give you better performance and use less memory than `GroupBy`. This is what the `Batch()` method of MoreLinq does IIRC.

score:44

We have just such a method in MoreLINQ as the Batch method:

``````// As IEnumerable<IEnumerable<T>>
var items = list.Batch(8);
``````

or

``````// As IEnumerable<List<T>>
var items = list.Batch(8, seq => seq.ToList());
``````