Rufen eine Sammlung mit LINQ

stimmen
69

Wie wollen Sie Seite durch eine Sammlung in LINQ gegeben , dass Sie eine haben startIndexund ein count?

Veröffentlicht am 01/08/2008 um 14:20
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
61

Es ist sehr einfach mit den Skipund TakeErweiterungsmethoden.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);
Beantwortet am 01/08/2008 um 14:22
quelle vom benutzer

stimmen
38

Vor ein paar Monaten schrieb ich einen Blog - Post über Fluent Interfaces und LINQ , die eine Erweiterungsmethode auf verwendet IQueryable<T>und eine andere Klasse die folgende natürliche Weise Paginieren eine LINQ - Sammlung zur Verfügung zu stellen.

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

: Sie können den Code aus der MSDN Code Gallery Seite erhalten Pipelines, Filter, Fluent API und LINQ to SQL .

Beantwortet am 07/08/2008 um 09:22
quelle vom benutzer

stimmen
12

Ich löste ein diesen etwas anders als das, was die andere haben, wie ich musste meine eigene paginator, mit einem Repeater machen. Also machte ich zum ersten Mal eine Sammlung von Seitenzahlen für die Sammlung von Gegenständen, die ich habe:

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

Mit diesem konnte ich partitionieren leicht das Element Sammlung in eine Sammlung von „Seiten“. Eine Seite ist in diesem Fall nur eine Sammlung von Gegenständen ( IEnumerable<Item>). Dies ist , wie Sie tun können , es zu benutzen Skipund Takezusammen mit dem Index aus der Auswahl pageRangeerstellt oben:

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

Natürlich müssen Sie jede Seite als eine zusätzliche Sammlung handhaben, aber wenn Sie zB Repeater nisten sind, dann ist dies eigentlich leicht zu handhaben.


Der Einzeiler TLDR Version wäre dies:

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

Was als diese verwendet werden können:

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

    for (Item item : page) 
    {
        // handle item in page
    }
}
Beantwortet am 20/03/2012 um 13:52
quelle vom benutzer

stimmen
9

Diese Frage ist etwas alt, aber ich wollte meinen Paging-Algorithmus schreiben, die das gesamte Verfahren (einschließlich Benutzer-Interaktion) zeigt.

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

Wenn Sie nach Leistung sind jedoch, und in der Produktion Code, sind wir alle nach Leistung, sollten Sie nicht LINQ Paging verwenden , wie oben gezeigt, sondern die zugrunde liegenden IEnumeratorselbst zu implementieren Paging. Wie in der Tat ist es so einfach wie der LINQ-Algorithmus , der oben gezeigt, aber leistungsfähigere:

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

Erläuterung: Der Nachteil der Verwendung Skip()für mehrfach in einem „kaskadenartig“ ist, dass es nicht wirklich speichert den „Zeiger“ der Iteration, wo sie zuletzt übersprungen. - Stattdessen wird die ursprüngliche Sequenz mit Sprung Anrufen von vorne geladen werden, was zu „raubend“ die bereits „verbraucht“ Seiten immer und immer wieder führen wird. - Sie können die selbst unter Beweis stellen, wenn Sie die Sequenz erstellen , ideasso dass es Nebenwirkungen ergibt. -> Auch wenn Sie übersprungen haben 10-20 und 20-30 und bearbeiten wollen 40+, finden Sie alle Nebenwirkungen von 10-30 sehen wieder ausgeführt wird, bevor Sie Iterieren 40+ starten. Die Variante mit IEnumerabledirekt ‚s - Schnittstelle, wird stattdessen die Position des Endes der letzten logischen Seite erinnern, so dass kein explizites Skipping ist erforderlich und Nebenwirkungen werden nicht wiederholt.

Beantwortet am 16/07/2011 um 21:07
quelle vom benutzer

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