Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

August 28, 2010

Divide a List into Equal Parts

Filed under: C#,VB.NET @ 6:43 pm

A recent post in the forums asked how to divide a generic list of items into separate lists of equal length.

For example, take a list of integers as shown below. Divide the list into separate lists of equal size (plus one list for the remaining elements).

In C#:

List<int> dd = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
                                11, 12, 13, 14, 15, 16, 17, 18, 19};

In VB:

Dim dd As New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                                11, 12, 13, 14, 15, 16, 17, 18, 19}

You can use the Skip and Take Enumerable extension methods for the task.

Here is the code:

In C#:

public List<List<int>> splitData(int width, List<int> dd)
{
    List<List<int>> dds = new List<List<int>>();

    // Determine how many lists are required
    int numberOfLists = (dd.Count / width);

    for (int i = 0; i <= numberOfLists; i++)
    {
        List<int> newdd();
        newdd = dd.Skip(i * width).Take(width).ToList();
        dds.Add(newdd);
    }

    return dds;
}

In VB:

Public Function splitData(ByVal width As Integer,
                          ByVal dd As List(Of Integer)) _
                      As List(Of List(Of Integer))

    Dim dds As New List(Of List(Of Integer))

    ‘ Determine how many lists are required
    Dim numberOfLists As Integer = (dd.Count \ width)

    For i As Integer = 0 To numberOfLists
        Dim newdd As List(Of Integer)
        newdd = dd.Skip(i * width).Take(width).ToList()
        dds.Add(newdd)
    Next i

    Return dds
End Function

This code first creates a List for the set of Lists. The number of equal sized lists is then calculated by dividing the number of items in the original list by the desired number of items in each list. In this case, there are 19 elements in the list. If the "width" is 4, then there will be 5 lists.

The loop creates each of the equal sized lists. It uses the Skip method to skip the appropriate number of elements. It then uses the Take method to take the appropriate number of elements for each list.

You call this method as follows:

In C#:

List<int> dd = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
                                11, 12, 13, 14, 15, 16, 17, 18, 19};

List<List<int>> splitdd = splitData(4, dd);

In VB:

Dim dd As New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                                11, 12, 13, 14, 15, 16, 17, 18, 19}

Dim splitdd As List(Of List(Of Integer)) = splitData(4, dd)

Use this technique any time you want to use parts of a list to build another list.

Enjoy!

EDIT 9/1/2010: Inadvertently included a new when creating the List<int>. Removed it in both code examples. Thanks to Richard for pointing this out.

3 Comments

  1.   Richard — September 1, 2010 @ 1:34 pm    Reply

    “List newdd = new List();
    newdd = dd.Skip(i * width).Take(width).ToList();”

    You’ve created a new List instance, and then immediately thrown it away. This increases the GC churn and will have a negative impact on performance.

    Also, your method is needlessly restrictive. Why not try something like:

    public static IEnumerable> SplitData(this IEnumerable source, int listSize)
    {
    while (source.Any())
    {
    yield return source.Take(listSize);
    source = source.Skip(listSize);
    }
    }

  2.   DeborahK — September 1, 2010 @ 1:38 pm    Reply

    Hi Richard –

    Thanks for your comments and alternative code.

    Yes, the new statement was unnecessary. I will update my post. Thanks for catching it.

  3.   osmirnov — September 23, 2010 @ 1:19 am    Reply

    Hi,

    More elegant solution:

    public static IEnumerable> Split(this IEnumerable source, int count)
    {
    // skipped source and count checks …

    return source
    .Select((v, i) => new { Index = i, Value = v })
    .GroupBy(iv => iv.Index / count)
    .Select(g => g.Select(v => v.Value).ToList())
    .ToList();
    }

    By source: http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2020 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs