Divide array into an array of subsequence array

This is quite cute:

static class ChunkExtension
{
    public static IEnumerable<T[]> Chunkify<T>(
        this IEnumerable<T> source, int size)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (size < 1) throw new ArgumentOutOfRangeException("size");
        using (var iter = source.GetEnumerator())
        {
            while (iter.MoveNext())
            {
                var chunk = new T[size];
                chunk[0] = iter.Current;
                for (int i = 1; i < size && iter.MoveNext(); i++)
                {
                    chunk[i] = iter.Current;
                }
                yield return chunk;
            }
        }
    }
}
static class Program
{
    static void Main(string[] args)
    {
        List<byte> bytes = new List<byte>() {
              1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
        var chunks = bytes.Chunkify(4);
        foreach (byte[] chunk in chunks)
        {
            foreach (byte b in chunk) Console.Write(b.ToString("x2") + " ");
            Console.WriteLine();
        }
    }
}

Voted answer works if you always get source.Length % size != 0, though it is too verbose. Here goes a nicer implementation:

public static IEnumerable<T[]> AsChunks<T>(IEnumerable<T> source, int size)
{
    var chunk = new T[size];
    var i = 0;
    foreach(var e in source)
    {
        chunk[i++] = e;
        if (i==size)
        {
            yield return chunk;
            i=0;
        }
    }
    if (i>0) // Anything left?
    {
        Array.Resize(ref chunk, i);
        yield return chunk;
    }
}

void Main()
{
    foreach(var chunk in AsChunks("Hello World!",5))
        Console.WriteLine(new string(chunk));
}

Producing:

  1. Hello
  2. Worl
  3. d!

How about this:

var bytes = new List<byte>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

var result = Chunkify(bytes, 4);

IEnumerable<IEnumerable<T>> Chunkify<T>(IEnumerable<T> source, int chunkSize)
{
    var indicies = 
        Enumerable.Range(0, source.Count()).Where(i => i%chunkSize==0);

    var chunks = 
            indicies
            .Select( i => source.Skip(i).Take(chunkSize) )
            .Select( chunk => new { Chunk=chunk, Count=chunk.Count() } )
            .Select( c => c.Count < chunkSize ? c.Chunk.Concat( Enumerable.Repeat( default(T), chunkSize - c.Count ) ) : c.Chunk )
            ;

    return chunks;      
}

Tags:

C#