我需要遍历整个用户列表,但需要一次抓取20个。
foreach (var student in Class.Students.Take(20))
{
Console.WriteLine("You belong to Group " + groupNumber);
groupNumber++;
}
这样,前20个属于第1组,第二个20属于第2组,依此类推。
采用正确的语法吗?我相信Take将花费20来完成。谢谢!
答案 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);
}
}