Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Iterate through an IEnumerable several elements at a time

Tags:

c#

.net

linq

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?

like image 604
Dan Avatar asked Dec 07 '22 04:12

Dan


2 Answers

An efficient approach would be with an 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);
        }
    }
}

You could use 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;.

like image 52
Michael Liu Avatar answered Dec 08 '22 18:12

Michael Liu


This snippet groups your array into sets of 3 elements, and then creates a user for each set.

    exampleData.Select((elem, index) => new {elem, index})
        .GroupBy(x => x.index/3)
        .Select(x => CreateUser(
                          x.ElementAt(0).elem,
                          x.ElementAt(1).elem,
                          x.ElementAt(2).elem));

Naturally, you'll need to make sure the array's length is a multiple of 3.

like image 41
dcastro Avatar answered Dec 08 '22 18:12

dcastro