код, который вы представите только перебирать элементы в списке один раз, а другие указали.
Однако, это только дает вам предметы для одной страницы. Если вы обрабатываете несколько страниц, вы должны вызывать этот код один раз для каждой страницы (потому что где-то вы должны увеличивать currentPage
, правильно?).
Что я имею в виду, что вы должны делать что-то вроде этого:
for (int currentPage = 0; currentPage < numPages; ++currentPage)
{
foreach (var item in items.Skip(currentPage*itemsPerPage).Take(itemsPerPage))
{
//Do stuff
}
}
Теперь, если вы что, то будет быть итерация несколько раз последовательности - один раз для каждой страницы. Первая итерация будет идти только до конца первой страницы, но следующая будет итерации от начала до конца второй страницы (через Skip()
и Take()
), а следующая будет выполнять итерацию с начала на конец третьей страницы. И так далее.
Чтобы избежать этого, вы можете написать метод расширения для IEnumerable<T>
, который разбивает данные на партии (которые вы также можете описать как «разбиение на страницы» данных на «страницы»).
Вместо того, чтобы просто представляя IEnumerable из IEnumerables, он может быть более полезным, чтобы обернуть каждую партию в классе, чтобы поставить индекс партии вместе с деталями в пакете, например, так:
public sealed class Batch<T>
{
public readonly int Index;
public readonly IEnumerable<T> Items;
public Batch(int index, IEnumerable<T> items)
{
Index = index;
Items = items;
}
}
public static class EnumerableExt
{
// Note: Not threadsafe, so not suitable for use with Parallel.Foreach() or IEnumerable.AsParallel()
public static IEnumerable<Batch<T>> Partition<T>(this IEnumerable<T> input, int batchSize)
{
var enumerator = input.GetEnumerator();
int index = 0;
while (enumerator.MoveNext())
yield return new Batch<T>(index++, nextBatch(enumerator, batchSize));
}
private static IEnumerable<T> nextBatch<T>(IEnumerator<T> enumerator, int blockSize)
{
do { yield return enumerator.Current; }
while (--blockSize > 0 && enumerator.MoveNext());
}
}
Это расширение метод не буферизует данные, и он только через него проходит через него один раз.
Учитывая этот метод расширения, он становится более читаемым для пакетной обработки элементов. Обратите внимание, что в этом примере перечислены все элементы для всех страниц, в отличие от примера OP, который выполняет только итерации через элементы для одной страницы:
var items = Enumerable.Range(10, 50); // Pretend we have 50 items.
int itemsPerPage = 20;
foreach (var page in items.Partition(itemsPerPage))
{
Console.Write("Page " + page.Index + " items: ");
foreach (var i in page.Items)
Console.Write(i + " ");
Console.WriteLine();
}
Поместите точку останова и посмотрите. –
Это только один раскол. Вы тоже звоните из цикла? –