Lapozás a gyűjtemény LINQ

szavazat
69

Hogyan lapozhatja a gyűjtemény LINQ adott, hogy van egy startIndex, és a count?

A kérdést 01/08/2008 14:20
a forrás felhasználó
Más nyelveken...                            


4 válasz

szavazat
61

Ez nagyon egyszerű, a Skipés Takehosszabbító módszereket.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);
Válaszolt 01/08/2008 14:22
a forrás felhasználó

szavazat
38

Néhány hónappal ezelőtt írtam egy blogbejegyzést Fluent interfészek és a LINQ, amely korábban egy kiterjesztés módszer a IQueryable<T>másik osztály, hogy a következő természetes módon paginating a LINQ gyűjtemény.

var query = from i in ideas
            select i;
var pagedCollection = query.InPagesOf(10);
var pageOfIdeas = pagedCollection.Page(2);

Tudod kap a kódot az MSDN Code Gallery Oldal: Csővezetékek, szűrők, Fluent API és a LINQ to SQL .

Válaszolt 07/08/2008 09:22
a forrás felhasználó

szavazat
9

Ez a kérdés kissé régi, de azt akartam, hogy közzétegye a paging algoritmust, amely azt mutatja, a teljes eljárás (beleértve a felhasználói beavatkozás).

const int pageSize = 10;
const int count = 100;
const int startIndex = 20;

int took = 0;
bool getNextPage;
var page = ideas.Skip(startIndex);

do
{
    Console.WriteLine("Page {0}:", (took / pageSize) + 1);
    foreach (var idea in page.Take(pageSize))
    {
        Console.WriteLine(idea);
    }

    took += pageSize;
    if (took < count)
    {
        Console.WriteLine("Next page (y/n)?");
        char answer = Console.ReadLine().FirstOrDefault();
        getNextPage = default(char) != answer && 'y' == char.ToLowerInvariant(answer);

        if (getNextPage)
        {
            page = page.Skip(pageSize);
        }
    }
}
while (getNextPage && took < count);

Azonban, ha Ön után a teljesítmény, és a gyártási kód, mindannyian teljesítése után, akkor ne használja a LINQ a lapozás a fent látható, hanem a mögöttes IEnumeratorvégrehajtása lapozás magad. Ami azt illeti, ez olyan egyszerű, mint a LINQ-algoritmus fent látható, de eredményes,:

const int pageSize = 10;
const int count = 100;
const int startIndex = 20;

int took = 0;
bool getNextPage = true;
using (var page = ideas.Skip(startIndex).GetEnumerator())
{
    do 
    {
        Console.WriteLine("Page {0}:", (took / pageSize) + 1);

        int currentPageItemNo = 0;
        while (currentPageItemNo++ < pageSize && page.MoveNext())
        {
            var idea = page.Current;
            Console.WriteLine(idea);
        }

        took += pageSize;
        if (took < count)
        {
            Console.WriteLine("Next page (y/n)?");
            char answer = Console.ReadLine().FirstOrDefault();
            getNextPage = default(char) != answer && 'y' == char.ToLowerInvariant(answer);
        }
    }
    while (getNextPage && took < count);
}

Magyarázat: A hátránya a Skip()több alkalommal a „lépcsőzetes módon” is, hogy nem igazán tárolja a „pointer” az iteráció, ahol utoljára kimarad. - Ahelyett, hogy az eredeti sorozat lesz orrnehéz skip hívások, ami vezet „fogyasztó” a már „elfogyasztott” oldalak újra és újra. - Meg tudja bizonyítani, hogy magát, amikor létrehozza a sorrend ideas, így a hozamok mellékhatásokat. -> Még ha kimarad 10-20 és 20-30 és szeretné feldolgozni 40+, látni fogod az összes mellékhatást 10-30 végrehajtás alatt újra, mielőtt elkezdené iterációjával 40+. A variáns a IEnumerable„s felület közvetlenül, ehelyett emlékszik a helyzet a végén az utolsó logikai oldalon, így nincs kifejezett kihagyás van szükség, és a mellékhatások nem kell megismételni.

Válaszolt 16/07/2011 21:07
a forrás felhasználó

szavazat
12

Én megoldotta ezt egy kicsit másképp, mint amit a többiek, mint volt, hogy a saját paginator, a repeater. Szóval először egy gyűjtemény oldalszámok gyűjtésére tételek van:

// assumes that the item collection is "myItems"

int pageCount = (myItems.Count + PageSize - 1) / PageSize;

IEnumerable<int> pageRange = Enumerable.Range(1, pageCount);
   // pageRange contains [1, 2, ... , pageCount]

Ezzel én is megoszthatjuk az elem gyűjtemény egy gyűjtemény „oldalak”. Egy oldal ebben az esetben csak egy gyűjtemény a tárgyak ( IEnumerable<Item>). Ez hogyan ez megtehető Skip, és Takeegyütt adja az index a pageRangefent létrehozott:

IEnumerable<IEnumerable<Item>> pageRange
    .Select((page, index) => 
        myItems
            .Skip(index*PageSize)
            .Take(PageSize));

Persze van, hogy kezelni minden oldalon, mint egy további gyűjtemény, de pl ha egymásba átjátszó, akkor ez valóban könnyen kezelhető.


Az egysoros TLDR változata lenne:

var pages = Enumerable
    .Range(0, pageCount)
    .Select((index) => myItems.Skip(index*PageSize).Take(PageSize));

Amelyeket fel lehet használni, mint a következő:

for (Enumerable<Item> page : pages) 
{
    // handle page

    for (Item item : page) 
    {
        // handle item in page
    }
}
Válaszolt 20/03/2012 13:52
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more