Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use LINQ to Convert a List to a List of Lists

Tags:

c#

linq

I have a list of values:

IList<V> values = { V1, V2, V3, V4, V5, V6, V7 };

I would like to convert the list into a list of lists, where each sub-list is a specified size. The size of each sub-list could vary. For example:

IList<IList<V>> values_size2 = { { V1, V2 }, { V3, V4 }, { V5, V6 }, { V7 } };
IList<IList<V>> values_size3 = { { V1, V2, V3 }, { V4, V5, V6 }, { V7 } };
IList<IList<V>> values_size4 = { { V1, V2, V3, V4 }, { V5, V6, V7 } };

I could probably do this pretty easily using nested loops, but was wondering if there was a clever way to do this using LINQ?

My initial thought would be to use the Aggregate method somehow, but nothing comes to mind right away.

Thanks.

like image 663
dana Avatar asked Dec 11 '22 19:12

dana


1 Answers

Here is a generic IEnumerable based Batch function. You can just change the return type from IEnumerable<IEnumerable<T>> to IEnumerable<IList<T>> with no other changes (since in my implementation it's already a list. To change the whole thing to return a list of lists you'd need to either call `ToList on the result, or make a more involved refactor.

Note that technically this isn't using LINQ, it's just creating a new method that uses the same style and patterns commonly used by LINQ.

public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source
    , int batchSize)
{
    //TODO validate parameters

    List<T> buffer = new List<T>();

    foreach (T item in source)
    {
        buffer.Add(item);

        if (buffer.Count >= batchSize)
        {
            yield return buffer;
            buffer = new List<T>();
        }
    }
    if (buffer.Count >= 0)
    {
        yield return buffer;
    }
}
like image 182
Servy Avatar answered Jan 28 '23 07:01

Servy