如何在foreach循环中对迭代的元素进行分段

Hai*_*ter 9 c# linq foreach

我需要循环遍历整个用户列表,但需要一次抓取20个.

foreach (var student in Class.Students.Take(20))
{
   Console.WriteLine("You belong to Group " + groupNumber);
   groupNumber++;
}
Run Code Online (Sandbox Code Playgroud)

这样,前20个将属于组1,第二个20属于组2,依此类推.

采取正确的语法吗?我相信Take将花费20来完成.谢谢!

Mik*_*keP 15

你可以这样做:

int i = 0;
foreach (var grouping in Class.Students.GroupBy(s => ++i / 20))
    Console.WriteLine("You belong to Group " + grouping.Key.ToString());
Run Code Online (Sandbox Code Playgroud)

  • 由于预增量,此代码是否具有逐个错误?从本质上讲,你是从`i = 1`而不是0开始迭代.例如,如果你的组大小为2,那么可枚举的第一个元素将在第一个分组中自行完成,因为`( 0 + 1)/ 2 == 0`但是`(1 + 1)/ 2 == 1`. (2认同)

Ger*_*old 9

对于类似的问题,我曾经做过一个扩展方法:

public static IEnumerable<IEnumerable<T>> ToChunks<T>(this IEnumerable<T> enumerable, int chunkSize)
{
    int itemsReturned = 0;
    var list = enumerable.ToList(); // Prevent multiple execution of IEnumerable.
    int count = list.Count;
    while (itemsReturned < count)
    {
        int currentChunkSize = Math.Min(chunkSize, count - itemsReturned);
        yield return list.GetRange(itemsReturned, currentChunkSize);
        itemsReturned += currentChunkSize;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,最后一个块可能小于指定的块大小.

编辑 使用的第一个版本Skip()/Take(),但克里斯指出,GetRange速度要快得多.

  • GetRange比Skip/Take快4000倍 (2认同)
  • 嘿,谢谢@ChrisGessler.如果发现自己忽视了一种能做得更好的"好老"方法的存在,那就太尴尬了(虽然我总是对自己说,linq不是一切的答案).在一个包含大量和非原始对象的基准测试中,我发现GetRange比"Skip()/ Take()"有10倍的改进.好决定. (2认同)