Questa è la stessa della risposta accettata, ma una rappresentazione molto più semplice:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
Il metodo precedente divide un IEnumerable<T>
in un numero di blocchi di dimensioni uguali o vicine a dimensioni uguali.
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
Il metodo sopra divide un IEnumerable<T>
in blocchi della dimensione fissa desiderata con il numero totale di blocchi non importante, che non è ciò di cui si tratta.
Il problema con il Split
metodo, oltre ad essere più lento, è che rimescola l'output nel senso che il raggruppamento sarà fatto sulla base dell'i-esimo multiplo di N per ogni posizione, o in altre parole non si ottengono i blocchi nell'ordine originale.
Quasi ogni risposta qui o non conserva l'ordine, o riguarda il partizionamento e non la divisione, o è chiaramente sbagliata. Prova questo che è più veloce, preserva l'ordine ma un po 'più prolisso:
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);
}
Il metodo equivalente per Partition
un'operazione qui