É o mesmo que a resposta aceita, mas uma representação muito mais simples:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
O método acima divide um IEnumerable<T>
em N número de pedaços de tamanhos iguais ou quase iguais.
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
O método acima divide um IEnumerable<T>
em pedaços do tamanho fixo desejado com o número total de pedaços sem importância - e não é disso que se trata.
O problema com o Split
método, além de ser mais lento, é que ele embaralha a saída no sentido de que o agrupamento será feito com base no i-ésimo múltiplo de N para cada posição ou, em outras palavras, você não recebe os pedaços na ordem original.
Quase todas as respostas aqui não preservam a ordem, ou são sobre particionamento e não são divididas, ou estão claramente erradas. Tente isso mais rápido, preserva a ordem, mas um pouco mais detalhado:
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);
}
O método equivalente para uma Partition
operação aqui