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

时间:2011-07-27 18:27:30

标签: c# linq foreach

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

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

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

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

3 个答案:

答案 0 :(得分:15)

您可以这样做:

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

答案 1 :(得分: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;
    }
}

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

修改 第一个版本使用Skip()/Take(),但克里斯指出,GetRange要快得多。

答案 2 :(得分:0)

您可以使用Select和这样的匿名类型将组编号投影到原始列表中的每个项目上:

var assigned = Class.Students.Select(
  (item, index) => new 
  { 
    Student = item, 
    GroupNumber = index / 20 + 1 
  });

然后你可以像这样使用它:

foreach (var item in assigned)
{
  Console.WriteLine("Student = " + item.Student.Name);
  Console.WriteLine("You belong to Group " + item.GroupNumber.ToString());
}

或者如果你想摘下一个特定的小组。

foreach (var student in assigned.Where(x => x.GroupNumber == 5))
{
  Console.WriteLine("Name = " + student.Name);
}

或者,如果您想实际将它们分组以执行聚合

foreach (var group in assigned.GroupBy(x => x.GroupNumber))
{
  Console.WriteLine("Average age = " + group.Select(x => x.Student.Age).Average().ToString());
}

现在,如果您只想批量生产物品并且不关心批号信息,可以创建这种简单的扩展方法。

public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> target, int size)
{
  var assigned = target.Select(
      (item, index) => new
      {
          Value = item,
          BatchNumber = index / size
      });
  foreach (var group in assigned.GroupBy(x => x.BatchNumber))
  {
      yield return group.Select(x => x.Value);
  }
}

您可以像这样使用新的扩展方法。

foreach (var batch in Class.Students.Batch(20))
{
  foreach (var student in batch)
  {
    Console.WriteLine("Student = " + student.Name);
  }
}