我正在开发一个ac#program,它有一个"IEnumerable users",可以存储400万用户的ID.我需要遍历Ienummerable并每次提取批量1000个ID以在另一个方法中执行某些操作.
如何从Ienumerable开始一次提取1000个ID ...做一些其他事情然后获取下一批1000等等?
这可能吗?
Ser*_*kiy 129
您可以使用MoreLINQ的Batch运算符(可从NuGet获得):
foreach(IEnumerable<User> batch in users.Batch(1000))
// use batch
Run Code Online (Sandbox Code Playgroud)
如果不能选择简单使用库,则可以重用实现:
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)
{
Array.Resize(ref bucket, count);
yield return bucket.Select(x => x);
}
}
Run Code Online (Sandbox Code Playgroud)
BTW的性能你可以简单地返回桶而不需要调用Select(x => x).Select针对数组进行了优化,但仍会在每个项目上调用选择器委托.所以,在你的情况下,最好使用
yield return bucket;
Run Code Online (Sandbox Code Playgroud)
Bil*_*ill 42
听起来你需要使用对象的Skip和Take方法.例:
users.Skip(1000).Take(1000)
Run Code Online (Sandbox Code Playgroud)
这将跳过前1000并接下来的1000.你只需要增加每次调用跳过的数量
您可以使用带跳过参数的整数变量,并可以调整跳过的数量.然后,您可以在方法中调用它.
public IEnumerable<user> GetBatch(int pageNumber)
{
return users.Skip(pageNumber * 1000).Take(1000);
}
Run Code Online (Sandbox Code Playgroud)
p.s*_*w.g 29
最简单的方法是使用GroupByLINQ中的方法:
var batches = myEnumerable
.Select((x, i) => new { x, i })
.GroupBy(p => (p.i / 1000), (p, i) => p.x);
Run Code Online (Sandbox Code Playgroud)
但是对于更复杂的解决方案,请参阅此博客文章,了解如何创建自己的扩展方法来执行此操作.这里重复了后人:
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;
}
Run Code Online (Sandbox Code Playgroud)
小智 17
怎么样
int batchsize = 5;
List<string> colection = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"};
for (int x = 0; x < Math.Ceiling((decimal)colection.Count / batchsize); x++)
{
var t = colection.Skip(x * batchsize).Take(batchsize);
}
Run Code Online (Sandbox Code Playgroud)
Zak*_*aki 11
试着用这个:
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;
}
Run Code Online (Sandbox Code Playgroud)
并使用上述功能:
foreach (var list in Users.Batch(1000))
{
}
Run Code Online (Sandbox Code Playgroud)
这样的事情会起作用:
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
}
Run Code Online (Sandbox Code Playgroud)
您可以将其概括为通用方法,如下所示:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49580 次 |
| 最近记录: |