Click here to Skip to main content
15,887,585 members
Articles / Programming Languages / C#
Tip/Trick

Get Chunky Now

Rate me:
Please Sign up or sign in to vote.
3.80/5 (3 votes)
15 Oct 2021CPOL 9.3K   4   7
Create collections of #n sized elements from arrays, lists, and string
This is an extension method that returns an IEnumerable<T> containing #n groups of Type T elements of arrays, lists, and string. In the case of a string: returns an IEnumerable<Char>

In a recent Insider News story, Bite-size-NET-6-Chunk-in-LINQ, the new Chunk features in .NET 6 are discussed. We are mere mortals that don't use the EF database context/pagination functions... have been chunking a long time; my version works with lists/arrays of any type, including DateTime, TimeSpan and single strings (returns chunks of Type Char):

C#
//
// required
using System;
using System.Collections.Generic;
using System.Linq;

public static class ChunkExtensions
{
    public static IEnumerable<List<T>> GetChunks<T>(this IEnumerable<T> source, int chunksize)
    {
        int cnt = source.Count();

        if (cnt == 0) yield return null;

        // required to enable 'GetRange
        List<T> slist = source.ToList();

        if (chunksize <= 0 || chunksize >= cnt) //  alternative ? throw error
        {
            yield return slist;
            yield break;
        }
        
        int rem = cnt % chunksize;
        int lastchunkstart = cnt - rem;

        for (int i = 0; i < lastchunkstart; i += chunksize)
        {
            yield return slist.GetRange(i, chunksize);
        }

        if (rem > 0)
        {
            yield return slist.GetRange(lastchunkstart, rem);
        }
    }
}

// usage example

List<int> ints = Enumerable.Range(0, 100).ToList();

List<List<int>> chunk27 = ints.GetChunks(27).ToList();

for (int i = 0; i < chunk27.Count; i++)
{
    List<int> chunk = chunk27[i];
    Console.WriteLine($"chunk {i} : #items {chunk.Count}");
}

// output:

chunk 0 : #items 27
chunk 1 : #items 27
chunk 2 : #items 27
chunk 3 : #items 19

History

  • 16th October, 2021: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer
Thailand Thailand
Human being, mortal, flawed.

Comments and Discussions

 
SuggestionImprovement Pin
Richard Deeming17-Oct-21 22:17
mveRichard Deeming17-Oct-21 22:17 
GeneralRe: Improvement Pin
BillWoodruff17-Oct-21 23:17
professionalBillWoodruff17-Oct-21 23:17 
GeneralRe: Improvement Pin
Richard Deeming17-Oct-21 23:32
mveRichard Deeming17-Oct-21 23:32 
GeneralRe: Improvement Pin
BillWoodruff18-Oct-21 1:25
professionalBillWoodruff18-Oct-21 1:25 
thanks !
Richard Deeming wrote:
That would fix the multiple enumeration. You would still end up holding the entire sequence in memory, which could cause problems for large (or infinite) lists.
There is some interesting complexity here due to the CLR/internal short-circuit behavior of Count():
// source excerpt
ICollection<T> c = source as ICollection<TSource>;
if (c != null) return c.Count();
If i pass in an IEnumerable, Count() iterates; pass in an Array, List; no iteration. i wonder if there's something could be exploited here. it's a mystery to me how the cast to ICollection enables Count; w/o iteration Smile | :)

My current view is changing as i ask: if you have got to call 'ToList() ... why not always return the iterated collection ?
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch


modified 18-Oct-21 9:06am.

GeneralRe: Improvement Pin
Richard Deeming18-Oct-21 1:33
mveRichard Deeming18-Oct-21 1:33 
GeneralRe: Improvement Pin
BillWoodruff18-Oct-21 3:45
professionalBillWoodruff18-Oct-21 3:45 
GeneralRe: Improvement Pin
Richard Deeming18-Oct-21 4:08
mveRichard Deeming18-Oct-21 4:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.