Paging kolekci s LINQ

hlasů
69

Jak se vám stránka přes sbírky v LINQ za předpokladu, že máte startIndexa count?

Položena 01/08/2008 v 14:20
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
61

Je to velmi jednoduché se Skipa Takerozšíření metod.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);
Odpovězeno 01/08/2008 v 14:22
zdroj uživatelem

hlasů
38

Před několika měsíci jsem napsal blog post o Fluent rozhraní a LINQ, který použil metodu rozšíření na IQueryable<T>a jiné třídy poskytnout následující přirozený způsob paginating sbírku LINQ.

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

Můžete získat kód od kódu MSDN galerie Stránka: Potrubí, filtry, Fluent API a LINQ to SQL .

Odpovězeno 07/08/2008 v 09:22
zdroj uživatelem

hlasů
12

vyřešil jsem to trochu jinak, než to, co jiní mají, jak jsem musel udělat svůj vlastní paginator, s opakovač. Tak jsem se poprvé kolekci čísla stránek pro shromažďování položek, které mám:

// 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]

Použití této skutečnosti jsem mohl snadno rozdělit sbírku položky do sbírky „stránek“. Stránka je v tomto případě jen sbírka předmětů ( IEnumerable<Item>). To je, jak můžete to udělat pomocí Skipa Takespolu s výběrem index kombinuje na pageRangevytvořili výše:

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

Samozřejmě budete muset zvládnout každé stránky jako další kolekci, ale například v případě, že jste hnízdění opakovače, pak je to skutečně snadno ovladatelná.


Jednořádkový TLDR verze by bylo toto:

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

Které mohou být použity jako toto:

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

    for (Item item : page) 
    {
        // handle item in page
    }
}
Odpovězeno 20/03/2012 v 13:52
zdroj uživatelem

hlasů
9

Tato otázka je poněkud starý, ale chtěl jsem psát svůj algoritmus stránkování, která zobrazuje celý proces (včetně interakce s uživatelem).

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);

Nicméně, pokud jste po výkonu, a v kódu výroby, jsme všichni po výkonu, neměli byste používat LINQ to stránkování jak je uvedeno výše, ale spíše základní IEnumeratorimplementovat stránkování sami. Jako ve skutečnosti, je to tak jednoduché, jak LINQ algoritmus je uvedeno výše, ale výkonnější:

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);
}

Vysvětlení: Nevýhodou použití Skip()pro více časů v „kaskádovým způsobem“, je, že to nebude opravdu uložit „ukazatel“ na iterace, kde to bylo naposledy přeskočí. - Místo původní sekvence bude front-naložený skip hovory, které povedou k „spotřebovávají“ již „spotřebovaných“ stránek znovu a znovu. - můžete dokázat, že sám při vytváření sledu ideastak, že se získá vedlejší účinky. -> I když jste přeskočili 10-20 a 20-30 a chcete zpracovat 40+, uvidíte všechny vedlejší účinky 10-30 je opět spuštěn, než začnete iterace 40+. Varianta s použitím IEnumerable‚s rozhraní přímo, místo toho pamatovat pozici na konci minulého logické stránce, takže není potřeba žádné explicitní přeskakování a nežádoucí účinky se již nebude opakovat.

Odpovězeno 16/07/2011 v 21:07
zdroj uživatelem

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