To split the C# list into N Sub lists use the next generic helper:
public static class ListExtensions { public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize) { return source .Select((x, i) => new { Index = i, Value = x }) .GroupBy(x => x.Index / chunkSize) .Select(x => x.Select(v => v.Value).ToList()) .ToList(); } }
Split Example
Here is the list of 7 persons. And I want to split it into chunks in size 2. As a result, we should have 3 chunks with 2 persons and 1 chunk with 1 person. And at the end of the program, I print results grouped by chunks.
The full code example:
using System; using System.Linq; using System.Collections; using System.Collections.Generic; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { var personList = new List<Person>(); personList.Add(new Person() { Id =10, FirstName = "Belinda", LastName = "Mcintosh" }); personList.Add(new Person() { Id = 20, FirstName = "Cory", LastName = "Mcmahon" }); personList.Add(new Person() { Id = 30, FirstName = "Joe", LastName = "Horton" }); personList.Add(new Person() { Id = 40, FirstName = "Virginia", LastName = "Rice" }); personList.Add(new Person() { Id = 50, FirstName = "Kody", LastName = "Taylor" }); personList.Add(new Person() { Id = 60, FirstName = "Gordon", LastName = "Mercer" }); personList.Add(new Person() { Id = 70, FirstName = "Carolina", LastName = "Mcintosh" }); const int chunkSize = 2; var chunks = personList.ChunkBy<Person>(chunkSize); int i=0; foreach(var c in chunks) { i++; Console.WriteLine($"Chucnk #{i}"); foreach(var person in c) { Console.WriteLine($"{person.FirstName} {person.LastName}"); } Console.WriteLine(Environment.NewLine); } } } public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } public static class ListExtensions { public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize) { return source .Select((x, i) => new { Index = i, Value = x }) .GroupBy(x => x.Index / chunkSize) .Select(x => x.Select(v => v.Value).ToList()) .ToList(); } } }
Print Result(sorry for typo):
How Does it Work?
Let’s debug each line and see what intermediate results we have on lambda expressions. To simplify our example I rewrote it in a shorter manner without a generic function:
Output:
The ‘tmp1‘ variable contains the list of anonymous objects: {Index, Value(aka Person)}.
The ‘tmp2‘ contains GroupedEnumerable. To understand how Group calculates I prepared a ‘debug‘ table:
Index | Chunk Size | Group(integer division Index/ChunkSize) |
0 | 2 | 0 |
1 | 2 | 0 |
2 | 2 | 1 |
3 | 2 | 1 |
4 | 2 | 2 |
5 | 2 | 2 |
6 | 2 | 3 |
How to Split List into Sub List if you use .net 6 and C# 10
If you use C# 10 you can find a new function Chunk. Look at my article about LINQ improvement in .NET 6 where I describe how the above code could be replaced by the Chunk function.
You may also be interested in reading: