Kod że przedstawienie będzie iteracyjne tylko pozycje z listy raz, jak inni zwrócili uwagę.
Jednak daje to tylko pozycje dla jednej strony. Jeśli obsługujesz wiele stron, musisz wywoływać ten kod raz dla każdej strony (ponieważ gdzieś musisz zwiększyć wartość currentPage
, prawda?).
Chodzi mi o to, że trzeba robić coś takiego:
for (int currentPage = 0; currentPage < numPages; ++currentPage)
{
foreach (var item in items.Skip(currentPage*itemsPerPage).Take(itemsPerPage))
{
//Do stuff
}
}
Teraz, jeśli zrobić że, wtedy będzie być iteracji sekwencji wiele razy - raz dla każdej strony. Pierwsza iteracja potrwa tylko do końca pierwszej strony, ale następna będzie powtarzać od początku do końca drugiej strony (przez Skip()
i Take()
) - a następna będzie iterować od początku do końca koniec trzeciej strony. I tak dalej.
Aby tego uniknąć, można napisać metodę rozszerzenia dla IEnumerable<T>
, która dzieli dane na partie (które można również opisać jako "dzielenie na strony" danych na "strony").
Zamiast po prostu prezentuje IEnumerable z IEnumerables, może być bardziej przydatna owinąć każdą partię w klasie dostarczyć indeks partii wraz z pozycji w partii, tak jak poniżej:
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());
}
}
To rozszerzenie metoda nie buforuje danych, a tylko iteruje za jej pomocą tylko jeden raz.
Dzięki tej metodzie rozszerzenia staje się bardziej czytelna do grupowania elementów. Zauważ, że ten przykład wylicza poprzez wszystkie przedmioty dla wszystkich stron, w przeciwieństwie np PO, która tylko iteracji pozycji na jednej stronie:
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();
}
umieścić punkt załamania i zobaczyć. –
To tylko jeden podział. Czy to też nazywasz z pętli? –