How can I split an IEnumerable<String> into groups of IEnumerable<string> [duplicate]
I have an IEnumerable<string
> which I would like to split into groups of three so if my input had 6 items i would get a IEnumerable<IEnumerable<string>>
returned with two items each of which would contain an IEnumerable<string>
which my string contents in it.
I am looking for how to do this with Linq rather than a simple for loop
Thanks
var result = sequence.Select((s, i) => new { Value = s, Index = i })
.GroupBy(item => item.Index / 3, item => item.Value);
Note that this will return an IEnumerable<IGrouping<int,string>>
which will be functionally similar to what you want. However, if you strictly need to type it as IEnumerable<IEnumerable<string>>
(to pass to a method that expects it in C# 3.0 which doesn't support generics variance,) you should use Enumerable.Cast
:
var result = sequence.Select((s, i) => new { Value = s, Index = i })
.GroupBy(item => item.Index / 3, item => item.Value)
.Cast<IEnumerable<string>>();
This is a late reply to this thread, but here is a method that doesn't use any temporary storage:
public static class EnumerableExt
{
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> input, int blockSize)
{
var enumerator = input.GetEnumerator();
while (enumerator.MoveNext())
{
yield return nextPartition(enumerator, blockSize);
}
}
private static IEnumerable<T> nextPartition<T>(IEnumerator<T> enumerator, int blockSize)
{
do
{
yield return enumerator.Current;
}
while (--blockSize > 0 && enumerator.MoveNext());
}
}
And some test code:
class Program
{
static void Main(string[] args)
{
var someNumbers = Enumerable.Range(0, 10000);
foreach (var block in someNumbers.Partition(100))
{
Console.WriteLine("\nStart of block.");
foreach (int number in block)
{
Console.Write(number);
Console.Write(" ");
}
}
Console.WriteLine("\nDone.");
Console.ReadLine();
}
}
However, do note the comments below for the limitations of this approach:
-
If you change the
foreach
in the test code toforeach (var block in someNumbers.Partition(100).ToArray())
then it doesn't work any more. -
It isn't threadsafe.