3

I must convert from python language to C# some code and I'm having difficulties with one part of it.

def split_data(seq, length):
    return [seq[i:i + length] for i in range(0, len(seq), length)]

print(split_data([4,5,6,8,5],2))

The purpose of this code is to give an int array in parameters and split it in arrays of the length parameter. For instance here the result of this print will be : [[4, 5], [6, 8], [5]]

The thing is I need to have the same thing in C#. So I started to create a List<int[]>. I know how to add int[] inside of it but I have no idea how to split them as in Python, especially using this length parameter.

I tried to achieve it using for, foreach loops or even IEnumerable but I couldn't make it work

Maybe there is a very easy way to finish it or something I didn't notice yet. My low knowledge about C# is not helping me either :).

Thanks for your help anyway.

thomashoareau
  • 99
  • 1
  • 1
  • 10
  • Possible duplicate of [Create batches in linq](https://stackoverflow.com/questions/13731796/create-batches-in-linq) – Patrick Artner Apr 23 '18 at 10:36
  • other dupes : [split-list-into-sublists-with-linq](https://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq) and [split-an-ienumerablet-into-fixed-sized-chunks-return-an-ienumerableienumerab](https://stackoverflow.com/questions/13709626/split-an-ienumerablet-into-fixed-sized-chunks-return-an-ienumerableienumerab). Please revisit [how-to-ask](https://stackoverflow.com/help/how-to-ask) and pay special attention to what comes before asking questions: **Research** - thanks. – Patrick Artner Apr 23 '18 at 10:37

2 Answers2

6

Here's a solution using yield return:

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> seq, int length) {
    // figure out how many little sequences we need to create
    int count = seq.Count();
    int numberOfTimes = count % length == 0 ? count / length : count / length + 1;

    for (int i = 0 ; i < numberOfTimes ; i++) {
        yield return seq.Take(length);
        seq = seq.Skip(length);
    }
}

Usage:

new int[] {1,2,3,4,5,6,7}.Split(2)
Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

This should do it. It's generic so it should work with any array, no matter which type it is.

/// <summary>
/// Splits an array into sub-arrays of a fixed length. The last entry will only be as long as the amount of elements inside it.
/// </summary>
/// <typeparam name="T">Type of the array</typeparam>
/// <param name="array">Array to split.</param>
/// <param name="splitLength">Amount of elements in each of the resulting arrays.</param>
/// <returns>An array of the split sub-arrays.</returns>
public static T[][] SplitArray<T>(T[] array, Int32 splitLength)
{
    List<T[]> fullList = new List<T[]>();
    Int32 remainder = array.Length % splitLength;
    Int32 last = array.Length - remainder;
    for (Int32 i = 0; i < array.Length; i += splitLength)
    {
        // Get the correct length in case this is the last one
        Int32 currLen = i == last ? remainder : splitLength;
        T[] currentArr = new T[currLen];
        Array.Copy(array, i, currentArr, 0, currLen);
        fullList.Add(currentArr);
    }
    return fullList.ToArray();
}
Nyerguds
  • 5,360
  • 1
  • 31
  • 63