Reputation: 955
I have a list of bytes and I want to split this list into smaller parts.
var array = new List<byte> {10, 20, 30, 40, 50, 60};
This list has 6 cells. For example, I want to split it into 3 parts containing each 2 bytes.
I have tried to write some for loops and used 2D arrays to achieve my purpose but I don't know it is a correct approach.
byte[,] array2D = new byte[window, lst.Count / window];
var current = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array2D[i, j] = lst[current++];
}
}
Upvotes: 38
Views: 65531
Reputation: 8949
As of .Net 6 you can use IEnumerable.Chunk()
Here is an example:
int parts = 4;
int[] items =
{
1, 2, 3, 4, 5, 6, 7
};
int chunkSize = (int)Math.Round(decimal.ToDouble(decimal.Divide(items.Count(), parts)));
Console.WriteLine($"chunkSize: {chunkSize}");
int chunkNumber = 1;
foreach (int[] chunk in items.Chunk(chunkSize))
{
Console.WriteLine($"Chunk {chunkNumber++}:");
foreach (int item in chunk)
{
Console.WriteLine($" {item}");
}
Console.WriteLine();
}
Try it in Dotnet fiddle here
Upvotes: 4
Reputation: 21
You can make an extension method:
public static class IEnumerableExtensions
{
public static IEnumerable<T[]> Split<T>(this IEnumerable<T> self, int chunkSize)
{
using var enu = self.GetEnumerator();
var buffer = new List<T>();
while(enu.MoveNext())
{
var v = enu.Current;
buffer.Add(v);
if (buffer.Count != chunkSize) continue;
yield return buffer.ToArray();
buffer = new List<T>();
}
if (buffer.Count == 0) yield break;
yield return buffer.ToArray();
}
}
And use it like this:
var test = Enumerable.Range(0, 200);
var split = test.Split(7).ToArray();
Upvotes: 0
Reputation: 71
Public Shared Function splitArrayIntoSmallerArrays(Of someObject)(arrayOfSomeObject As someObject(), chunkSize As Integer) As List(Of someObject())
Dim output = New List(Of someObject())
Dim newestArray = New List(Of someObject)
For i = 0 To arrayOfSomeObject.Count - 1
newestArray.Add(arrayOfSomeObject(i))
If newestArray.Count = chunkSize Then
output.Add(newestArray.ToArray)
newestArray = New List(Of someObject)
End If
Next
output.Add(newestArray.ToArray)
Return output
End Function
Upvotes: 0
Reputation: 77
If you have an array to be divided but the division has the rest with this simple solution you can share the elements missing into the various "chunks" equally:
public static List<int[]> SplitArrey(int[] arrInput, int nColumn) {
List<int[]> result = new List<int[]>(nColumn);
int itemsForColum = arrInput.Length / nColumn;
int countSpareElement = arrInput.Length - (itemsForColum * nColumn);
// Add and extra space for the spare element
int[] newColumLenght = new int[nColumn];
for (int i = 0; i < nColumn; i++)
{
int addOne = (i < countSpareElement) ? 1 : 0;
newColumLenght[i] = itemsForColum + addOne;
result.Add(new int[itemsForColum + addOne]);
}
// Copy the values
int offset = 0;
for (int i = 0; i < nColumn; i++)
{
int count_items_to_copy = newColumLenght[i];
Array.Copy(arrInput, offset, result[i], 0, count_items_to_copy);
offset += newColumLenght[i];
}
return result;
}
Then:
int[] arrInput = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
var result = SplitArrey(arrInput, 5);
foreach (var item in result) {
Console.WriteLine(" {0}", String.Join(" ", item));
}
the result is:
1 2 3
4 5 6
7 8
9 10
11 12
Upvotes: -1
Reputation: 7245
A nice way would be to create a generic/extension method to split any array. This is mine:
/// <summary>
/// Splits an array into several smaller arrays.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array to split.</param>
/// <param name="size">The size of the smaller arrays.</param>
/// <returns>An array containing smaller arrays.</returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
Moreover, this solution is deferred. Then, simply call Split(size)
on your array.
var array = new byte[] {10, 20, 30, 40, 50, 60};
var splitArray = array.Split(2);
As requested, here is a generic/extension method to get a square 2D arrays from an array:
/// <summary>
/// Splits a given array into a two dimensional arrays of a given size.
/// The given size must be a divisor of the initial array, otherwise the returned value is <c>null</c>,
/// because not all the values will fit into the resulting array.
/// </summary>
/// <param name="array">The array to split.</param>
/// <param name="size">The size to split the array into. The size must be a divisor of the length of the array.</param>
/// <returns>
/// A two dimensional array if the size is a divisor of the length of the initial array, otherwise <c>null</c>.
/// </returns>
public static T[,]? ToSquare2D<T>(this T[] array, int size)
{
if (array.Length % size != 0) return null;
var firstDimensionLength = array.Length / size;
var buffer = new T[firstDimensionLength, size];
for (var i = 0; i < firstDimensionLength; i++)
{
for (var j = 0; j < size; j++)
{
buffer[i, j] = array[i * size + j];
}
}
return buffer;
}
Have fun!
Upvotes: 82
Reputation: 5726
This to have list of lists
array.Select((s,i) => array.Skip(i * 2).Take(2)).Where(a => a.Any())
Or this to have list of items
array.SelectMany((s,i) => array.Skip(i * 2).Take(2)).Where(a => a.Any())
Upvotes: 8
Reputation: 6547
using Linq
public List<List<byte>> SplitToSublists(List<byte> source)
{
return source
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 100)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
Simply use it
var sublists = SplitToSublists(lst);
Upvotes: 16
Reputation: 3626
You might want to give this a try.
var bytes = new List<byte>(10000);
int size = 100;
var lists = new List<List<byte>>(size);
for (int i = 0; i < bytes.Count; i += size)
{
var list = new List<byte>();
list.AddRange(bytes.GetRange(i, size));
lists.Add(list);
}
Upvotes: -1