C'est la même chose que la réponse acceptée, mais une représentation beaucoup plus simple:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
La méthode ci-dessus divise un IEnumerable<T>
nombre N de blocs de tailles égales ou proches de tailles égales.
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
La méthode ci-dessus divise un IEnumerable<T>
en morceaux de taille fixe souhaitée, le nombre total de morceaux étant sans importance - ce qui n'est pas le sujet de la question.
Le problème avec la Split
méthode, en plus d'être plus lente, est qu'elle brouille la sortie dans le sens où le regroupement se fera sur la base du i'ième multiple de N pour chaque position, ou en d'autres termes, vous n'obtenez pas les morceaux dans l'ordre d'origine.
Presque chaque réponse ici ne préserve pas l'ordre, ou concerne le partitionnement et non le fractionnement, ou est tout simplement erronée. Essayez ceci qui est plus rapide, préserve l'ordre mais un peu plus verbeux:
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);
}
La méthode équivalente pour une Partition
opération ici