This article explains how to split an arbitrary list of items into required number of groups/partitions, each group having equal number of items.

Splitting the List

The following C# function accepts a linear list of objects and required number of groups as arguments. The input list of objects is split into groups containing equal number of items. If the input list cannot be split equally, then the last group will contain the remaining items.

First the group-length (number of items for each group) is found, and then the input list is traversed from top to bottom in order to split it. The group-length is found by dividing the number-of-items by required number-of-groups, and rounding it off to zero decimal places (integer). An index variable (*startIndex*) is initialized to zero and is incremented by group-length for each iteration. During last iteration, if sufficient items are not available for last group, then the index variable is adjusted in order to hold the remaining number of items. After all iterations, the last two groups are merged if more than required groups are formed.

public static List<List<T>> SplitList<T>(List<T> items, int groupCount) { List<List<T>> allGroups = new List<List<T>>(); //split the list into equal groups int startIndex = 0; int groupLength = (int)Math.Round((double)items.Count / (double)groupCount, 0); while (startIndex < items.Count) { List<T> group = new List<T>(); group.AddRange(items.GetRange(startIndex, groupLength)); startIndex += groupLength; //adjust group-length for last group if (startIndex + groupLength > items.Count) { groupLength = items.Count - startIndex; } allGroups.Add(group); } //merge last two groups, if more than required groups are formed if (allGroups.Count > groupCount && allGroups.Count > 2) { allGroups[allGroups.Count - 2].AddRange(allGroups.Last()); allGroups.RemoveAt(allGroups.Count - 1); } return (allGroups); }

The following examples illustrate the usage of the *SplitList* function, defined above. A list of integers, say record-ids or record-numbers is split into groups of records. This list contains 11 items and is split into 3 groups, first and second group contains 4 items, and the last group contains 3 items. Then, a list of co-ordinates or points is split into groups. This list contains 5 items and is split into 2 groups, first group contains 2 items and second group contains 3 items. The *Point* is a simple class containing *X* and *Y* as properties.

List<int> recordNumbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; List<List<int>> recordGroups = SplitList<int>(recordNumbers, 3); List<Point> allPoints = new List<Point>(); allPoints.Add(new Point() { X = 5, Y = 2 }); allPoints.Add(new Point() { X = 3, Y = 1 }); allPoints.Add(new Point() { X = 1.5, Y = 2 }); allPoints.Add(new Point() { X = 13, Y = 7 }); allPoints.Add(new Point() { X = 5.1, Y = 3 }); List<List<Point>> pointGroups = SplitList<Point>(allPoints, 2);