我有一個對象集合,需要批量處理100個對象,並對它們進行一些處理,直到沒有剩餘的對象處理爲止。LINQ:從一個集合中獲取一系列元素
而不是循環通過每個項目,抓住100個元素,然後下一百等有沒有更好的方式與linq做呢?
非常感謝
我有一個對象集合,需要批量處理100個對象,並對它們進行一些處理,直到沒有剩餘的對象處理爲止。LINQ:從一個集合中獲取一系列元素
而不是循環通過每個項目,抓住100個元素,然後下一百等有沒有更好的方式與linq做呢?
非常感謝
static void test(IEnumerable<object> objects)
{
while (objects.Any())
{
foreach (object o in objects.Take(100))
{
}
objects = objects.Skip(100);
}
}
:)
如果在Entity Framework中使用此方法,請小心。它生成的SQL在每次迭代中都會有一個額外的子查詢。如果批次超過50個,則查詢失敗。 – 2013-10-07 11:31:16
int batchSize = 100;
var batched = yourCollection.Select((x, i) => new { Val = x, Idx = i })
.GroupBy(x => x.Idx/batchSize,
(k, g) => g.Select(x => x.Val));
// and then to demonstrate...
foreach (var batch in batched)
{
Console.WriteLine("Processing batch...");
foreach (var item in batch)
{
Console.WriteLine("Processing item: " + item);
}
}
我不認爲LINQ是真正適合這種處理的 - 這是用於對整個序列的操作,而不是分裂主要是有用的或修改它們。我會通過訪問底層的IEnumerator<T>
來做到這一點,因爲任何使用Take
和Skip
的方法都會非常低效。
public static void Batch<T>(this IEnumerable<T> items, int batchSize, Action<IEnumerable<T>> batchAction)
{
if (batchSize < 1) throw new ArgumentException();
List<T> buffer = new List<T>();
using (var enumerator = (items ?? Enumerable.Empty<T>()).GetEnumerator())
{
while (enumerator.MoveNext())
{
buffer.Add(enumerator.Current);
if (buffer.Count == batchSize)
{
batchAction(buffer);
buffer.Clear();
}
}
//execute for remaining items
if (buffer.Count > 0)
{
batchAction(buffer);
}
}
}
這會將列表分割成您指定的很多項目的列表列表。
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> source, int size)
{
int i = 0;
List<T> list = new List<T>(size);
foreach (T item in source)
{
list.Add(item);
if (++i == size)
{
yield return list;
list = new List<T>(size);
i = 0;
}
}
if (list.Count > 0)
yield return list;
}
var batchSize = 100;
for (var i = 0; i < Math.Ceiling(yourCollection.Count()/(decimal)batchSize); i++)
{
var batch = yourCollection
.Skip(i*batchSize)
.Take(batchSize);
// Do something with batch
}
LukeH的答案是好多了,請接受並使用它。 – Andrey 2010-10-06 13:22:08