Esto es lo mismo que la respuesta aceptada, pero una representación mucho más simple:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
El método anterior divide una IEnumerable<T>
N en un número de trozos de igual tamaño o casi iguales.
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
El método anterior divide un IEnumerable<T>
trozo en trozos del tamaño fijo deseado y el número total de trozos no es importante, de lo que no se trata la pregunta.
El problema con el Split
método, además de ser más lento, es que codifica la salida en el sentido de que la agrupación se realizará sobre la base de un múltiplo de N para cada posición, o en otras palabras, no obtendrá los fragmentos En el orden original.
Casi todas las respuestas aquí no conservan el orden, o se trata de particionar y no dividir, o simplemente es incorrecto. Pruebe esto, que es más rápido, conserva el orden pero un poco más detallado:
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);
}
El método equivalente para una Partition
operación aquí