To jest to samo, co przyjęta odpowiedź, ale o wiele prostsza reprezentacja:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
Powyższa metoda dzieli an IEnumerable<T>
na liczbę N fragmentów o równych lub zbliżonych rozmiarach.
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
Powyższa metoda dzieli plik IEnumerable<T>
na kawałki o pożądanym ustalonym rozmiarze, przy czym całkowita liczba fragmentów jest nieistotna - nie o to chodzi w pytaniu.
Problem z Split
metodą, poza tym, że jest wolniejsza, polega na tym, że szyfruje ona dane wyjściowe w tym sensie, że grupowanie zostanie wykonane na podstawie i-tej wielokrotności N dla każdej pozycji, lub innymi słowy, nie dostaniesz fragmentów w pierwotnej kolejności.
Prawie każda odpowiedź tutaj albo nie zachowuje porządku, albo dotyczy partycjonowania, a nie dzielenia, albo jest po prostu błędna. Spróbuj tego, co jest szybsze, zachowuje porządek, ale jest trochę bardziej szczegółowe:
public static IEnumerable<IEnumerable<T>> Split<T>(this ICollection<T> items,
int numberOfChunks)
{
if (numberOfChunks <= 0 || numberOfChunks > items.Count)
throw new ArgumentOutOfRangeException("numberOfChunks");
int sizePerPacket = items.Count / numberOfChunks;
int extra = items.Count % numberOfChunks;
for (int i = 0; i < numberOfChunks - extra; i++)
yield return items.Skip(i * sizePerPacket).Take(sizePerPacket);
int alreadyReturnedCount = (numberOfChunks - extra) * sizePerPacket;
int toReturnCount = extra == 0 ? 0 : (items.Count - numberOfChunks) / extra + 1;
for (int i = 0; i < extra; i++)
yield return items.Skip(alreadyReturnedCount + i * toReturnCount).Take(toReturnCount);
}
Równoważna metoda dla Partition
operacji tutaj