Divide List<T> into List<List<T>> Equally

Divide a collection into a collection of collections equally

Posted on October 24, 2017 9:05AM

I ran into a situation where I needed to equally divide collections due to pagination where I would have a maximum of 16 items per page. What happens if I have 17 items? It would be silly to put 16 on one page and one on another. Putting nine on one page and eight on another seemed to make more sense. I wrote the following code to solve my problem.

Code

    internal class Program
    {
        private static void Main()
        {
            Enumerable.Range(15, 36).ToList().ForEach(t => Console.WriteLine("(" + t + ")" + string.Join(",", Enumerable.Range(1, t).ToList().DivideDataEqually().Select(x => x.Count).ToList())));
        }
    }

    internal static class Helper
    {
        public static List<List<T>> DivideDataEqually<T>(this List<T> data, int maxPerCollection = 16)
        {
            var divisor = (int)Math.Floor(data.Count / Math.Ceiling((decimal)data.Count / maxPerCollection));
            divisor = data.Count % divisor < maxPerCollection && divisor != maxPerCollection ? divisor + 1 : divisor >= maxPerCollection ? maxPerCollection : divisor;
            return data.Select((x, i) => new { idx = i, v = x }).GroupBy(x => x.idx / divisor).Select(x => x.Select(v => v.v).ToList()).ToList();
        }
    }

Result From Code

(Number in List)List of returned collections and their counts

(15)15
(16)16
(17)9,8
(18)10,8
(19)10,9
(20)11,9
(21)11,10
(22)12,10
(23)12,11
(24)13,11
(25)13,12
(26)14,12
(27)14,13
(28)15,13
(29)15,14
(30)16,14
(31)16,15
(32)16,16
(33)12,12,9
(34)12,12,10
(35)12,12,11
(36)13,13,10
(37)13,13,11
(38)13,13,12
(39)14,14,11
(40)14,14,12
(41)14,14,13
(42)15,15,12
(43)15,15,13
(44)15,15,14
(45)16,16,13
(46)16,16,14
(47)16,16,15
(48)16,16,16
(49)13,13,13,10
(50)13,13,13,11