如何批量循环浏览IEnumerable

我正在开发ac#程序,它有一个“IEnumerable用户”,存储400万用户的ID。 我需要通过Ienummerable循环,每次提取一批1000个ID,以另一种方法执行一些操作。

我如何从Ienumerable的开始一次提取1000个ID …做一些其他事情然后获取下一批1000个等等?

这可能吗?

听起来就像你需要使用你的对象的Skip和Take方法。 例:

users.Skip(1000).Take(1000) 

这将跳过前1000,并采取下一个1000.你只需要增加每次调用跳过的金额

您可以使用带跳过参数的整数variables,您可以调整跳过的数量。 然后你可以用一个方法来调用它。

 public IEnumerable<user> GetBatch(int pageNumber) { return users.Skip(pageNumber * 1000).Take(1000); } 

您可以使用更多的LINQ 批处理方法(可从NuGet获得):

 foreach(IEnumerable<User> batch in users.Batch(1000)) // use batch 

如果简单使用库不是一个选项,你可以重用实现:

 public static IEnumerable<IEnumerable<T>> Batch<T>( this IEnumerable<T> source, int size) { T[] bucket = null; var count = 0; foreach (var item in source) { if (bucket == null) bucket = new T[size]; bucket[count++] = item; if (count != size) continue; yield return bucket.Select(x => x); bucket = null; count = 0; } // Return the last bucket with all remaining elements if (bucket != null && count > 0) yield return bucket.Take(count); } 

顺便说一句,你可以简单地返回bucket而不用调用Select(x => x) 。 Select对数组进行了优化,但是对每个项目仍然会调用select器委托。 所以,在你的情况下,最好使用

 yield return bucket; 

最简单的方法是使用LINQ中的GroupBy方法:

 var batches = myEnumerable .Select((x, i) => new { x, i }) .GroupBy(p => (pi / 1000), (p, i) => px); 

但是对于更复杂的解决scheme,请参阅此博客文章 ,了解如何创build自己的扩展方法。 复制在这里为后人:

 public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> collection, int batchSize) { List<T> nextbatch = new List<T>(batchSize); foreach (T item in collection) { nextbatch.Add(item); if (nextbatch.Count == batchSize) { yield return nextbatch; nextbatch = new List<T>(); // or nextbatch.Clear(); but see Servy's comment below } } if (nextbatch.Count > 0) yield return nextbatch; } 

尝试使用这个:

  public static IEnumerable<IEnumerable<TSource>> Batch<TSource>( this IEnumerable<TSource> source, int batchSize) { var batch = new List<TSource>(); foreach (var item in source) { batch.Add(item); if (batch.Count == batchSize) { yield return batch; batch = new List<TSource>(); } } if (batch.Any()) yield return batch; } 

并使用以上function:

 foreach (var list in Users.Batch(1000)) { } 

您可以使用Take和Skip Enumerable扩展方法来实现这一点。 有关使用结帐linq 101的更多信息

像这样的东西可以工作:

 List<MyClass> batch = new List<MyClass>(); foreach (MyClass item in items) { batch.Add(item); if (batch.Count == 1000) { // Perform operation on batch batch.Clear(); } } // Process last batch if (batch.Any()) { // Perform operation on batch } 

你可以把它推广到一个通用的方法,就像这样:

 static void PerformBatchedOperation<T>(IEnumerable<T> items, Action<IEnumerable<T>> operation, int batchSize) { List<T> batch = new List<T>(); foreach (T item in items) { batch.Add(item); if (batch.Count == batchSize) { operation(batch); batch.Clear(); } } // Process last batch if (batch.Any()) { operation(batch); } } 

您可以使用Take operator linq

链接: http : //msdn.microsoft.com/fr-fr/library/vstudio/bb503062.aspx