Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何分割foreach循环中迭代的元素_C#_Linq_Foreach - Fatal编程技术网

C# 如何分割foreach循环中迭代的元素

C# 如何分割foreach循环中迭代的元素,c#,linq,foreach,C#,Linq,Foreach,我需要循环浏览整个用户列表,但每次需要抓取20个 foreach (var student in Class.Students.Take(20)) { Console.WriteLine("You belong to Group " + groupNumber); groupNumber++; } 这样,前20个属于组1,后20个属于组2,依此类推 是否对此使用正确的语法?我相信需要20分钟才能完成。谢谢 您可以这样做: int i = 0; foreach (var groupi

我需要循环浏览整个用户列表,但每次需要抓取20个

foreach (var student in Class.Students.Take(20))
{
   Console.WriteLine("You belong to Group " + groupNumber);
   groupNumber++;
}
这样,前20个属于组1,后20个属于组2,依此类推


是否对此使用正确的语法?我相信需要20分钟才能完成。谢谢

您可以这样做:

int i = 0;
foreach (var grouping in Class.Students.GroupBy(s => ++i / 20))
    Console.WriteLine("You belong to Group " + grouping.Key.ToString());
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());
}

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

int i = 0;
foreach (var grouping in Class.Students.GroupBy(s => ++i / 20))
    Console.WriteLine("You belong to Group " + grouping.Key.ToString());
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());
}
然后你可以这样使用它:

int i = 0;
foreach (var grouping in Class.Students.GroupBy(s => ++i / 20))
    Console.WriteLine("You belong to Group " + grouping.Key.ToString());
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);
  }
}

对于类似的问题,我曾经提出了一种扩展方法:

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;
    }
}
公共静态IEnumerable ToChunks(此IEnumerable可枚举,int chunkSize)
{
int itemsreturn=0;
var list=enumerable.ToList();//防止多次执行IEnumerable。
int count=list.count;
while(itemsreturn
请注意,最后一个块可能小于指定的块大小

编辑
第一个版本使用了
Skip()/Take()
,但正如Chris指出的那样,
GetRange
要快得多。

谢谢MikeP!这很有帮助。如果我需要给一组中的每个学生分配一个特定的值,我会怎么做?我觉得我必须在某个时候对每个对象进行嵌套。分组对象对于分组到其中的元素也是可枚举的。因此,只需一个foreach(分组中的var student)就可以做到这一点。这段代码不是因为预增量而有一个off by one错误吗?本质上,您是从
i=1
开始迭代,而不是从0开始。例如,如果组大小为2,则可枚举的第一个元素将单独位于第一个分组中,因为
(0+1)/2==0
,但
(1+1)/2==1
。您犯了与许多其他海报相同的错误,这些海报后来删除了他们的回复。你不能连续拿20件物品;前二十名学生中的每一位都将属于不同的小组!此外,您实际上也没有对任何内容进行分组。如果你想在一个小组里迭代学生,你的方法会让你感到非常枯燥。@MikeP:是的,很好。固定的。我还将
grouped
重命名为
assigned
,以更好地反映实际发生的情况。如果OP真的想迭代某个特定组的学生,你可以做
assigned.Where(x=>x.GroupNumber==value)
assigned.GroupBy(x=>x.GroupNumber)
,尽管根据我在问题中看到的情况,这看起来没有必要。我想LINQ的一个有趣的方面是,有很多方法可以做同样的事情。无论如何,是的,我完全被
%
而不是
/
的东西噎住了。GetRange比Skip/TakeHey快4000多倍,谢谢@ChrisGessler。发现自己忽视了一种“好的旧的”方法的存在是令人尴尬的,这种方法做得更好(而我总是对自己说linq不是一切的答案)。在一个包含大量非原始对象的基准测试中,我发现GetRange比
Skip()/Take()
提高了10+以上。很好的回答。@GertArnold这是一个非常古老的答案,但您能否提供一个异步版本作为对我问题的回答: