Vra

Hoe doen jy die bladsy deur middel van'n versameling in LINQ gegee dat jy'n startIndex en'n count?

Was dit nuttig?

Oplossing

'n paar maande terug het ek geskryf het'n blog post oor Vlot Koppelvlakke en LINQ wat gebruik word om'n Verlenging Metode op IQueryable<T> en'n ander klas om die volgende te verskaf natuurlike manier van paginating'n LINQ versameling.

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

Jy kan die kode van die MSDN Kode Gallery-Bladsy: Pyplyne, Filters, Vlot API en LINQ te SQL.

Ander wenke

Dit is baie eenvoudig met die Skip en Take uitbreiding metodes.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);

Ek opgelos dit'n bietjie anders as wat die ander het as wat ek gehad het om my eie te maak paginator, met'n herhaler.So het ek die eerste keer gemaak is'n versameling van die bladsy nommers vir die versameling van items wat ek het:

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

Die gebruik van hierdie ek kon maklik partisie die item versameling in'n versameling van "bladsye".'n bladsy in hierdie geval is net'n versameling van items (IEnumerable<Item>).Dit is hoe jy dit kan doen met behulp Skip en Take saam met die kies van die indeks van die pageRange geskep hierbo:

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

Van die kursus wat jy het om te hanteer elke bladsy as'n bykomende versameling maar bv.as jy nes herhalers dan is dit eintlik maklik om te hanteer.


Die een-liner TLDR weergawe sou wees om hierdie:

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

Wat kan gebruik word as hierdie:

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

    for (Item item : page) 
    {
        // handle item in page
    }
}

Hierdie vraag is'n bietjie oud, maar ek wou om te post my blaai algoritme wat toon die hele proses (insluitend interaksie van die gebruiker).

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

Egter, as jy na prestasie, en in die produksie kode, ons is almal na prestasie, moet jy nie gebruik LINQ se blaai soos hierbo getoon, maar eerder die onderliggende IEnumerator te implementeer blaai jouself.As'n saak van die feit, dit is so eenvoudig soos die LINQ-algoritme hierbo getoon, maar meer performante:

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

Verduideliking:Die nadeel van die gebruik van Skip() vir verskeie kere in'n "waterval wyse" is, dat dit nie regtig die stoor van die "pointer" van die iterasie, waar dit was verlede oorgeslaan.- In plaas van die oorspronklike volgorde sal wees voor-gelaai met slaan oproepe, wat sal lei tot "verbruik" die reeds "verteer" bladsye oor en oor weer.- Jy kan bewys dat jy jouself, wanneer jy skep die volgorde ideas so dat dit opbrengste newe-effekte.-> Selfs as jy het oorgeslaan 10-20 en 20-30 en wil om te verwerk 40+, sal jy sien al die newe-effekte van 10-30 uitgevoer word weer, voordat jy begin iterating 40+.Die variant met behulp van IEnumerablese koppelvlak direk, in plaas daarvan sal onthou die posisie van die einde van die laaste logiese bladsy, sodat daar geen eksplisiete huppel is nodig en newe-effekte sal nie herhaal word nie.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top