Search code examples
c#.netlinq

.NET Iterate through an IEnumerable several elements at a time


Given a collection, I need to iterate through all the elements three (or some other amount) at a time. For example:

string[] exampleData = {"John", "Doe", "1.1.1990", "Jane", "Roe", "2.2.1980"}

for(int i = 0; i < exampleData.Length; i += 3) {
    CreateUser(foreName: exampleData[i], surName: exampleData[i+1], dateOfBirth: exampleData[i+2]);
} 

How could I efficiently reproduce this if exampleData was an IEnumerable instead of an array?


Solution

  • .NET 6 and later

    You can use the LINQ Chunk extension method:

    foreach (string[] chunk in exampleData.Chunk(3))
    {
        CreateUser(foreName: chunk[0], surName: chunk[1], dateOfBirth: chunk[2]);
    }
    

    .NET 5 and earlier

    You can write your own extension method:

    public static IEnumerable<IList<T>> ChunksOf<T>(this IEnumerable<T> sequence, int size)
    {
        List<T> chunk = new List<T>(size);
    
        foreach (T element in sequence)
        {
            chunk.Add(element);
            if (chunk.Count == size)
            {
                yield return chunk;
                chunk = new List<T>(size);
            }
        }
    }
    

    Call it like this:

    foreach (IList<string> chunk in exampleData.ChunksOf(3))
    {
        CreateUser(foreName: chunk[0], surName: chunk[1], dateOfBirth: chunk[2]);
    }
    

    Note that if sequence.Count() is not an integer multiple of size, then ChunksOf discards the last partial chunk. If instead you wanted to return a partial chunk, you could add to the end: if (chunk.Count > 0) yield return chunk;.