Τηλεειδοποίησης μια συλλογή με LINQ

ψήφοι
69

Πώς σας σελίδα μέσα από μια συλλογή με LINQ, δεδομένου ότι έχετε ένα startIndexκαι ένα count;

Δημοσιεύθηκε 01/08/2008 στις 14:20
πηγή χρήστη
Σε άλλες γλώσσες...                            


4 απαντήσεις

ψήφοι
61

Είναι πολύ απλό με τις Skipκαι Takeεπέκταση μεθόδους.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);
Απαντήθηκε 01/08/2008 στις 14:22
πηγή χρήστη

ψήφοι
38

Λίγους μήνες πίσω έγραψα ένα blog post σχετικά με άριστα Διασυνδέσεις και LINQ που χρησιμοποιείται μια μέθοδος Παράταση για IQueryable<T>και μια άλλη κατηγορία για να παρέχει τις ακόλουθες φυσικό τρόπο paginating μια συλλογή LINQ.

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

Μπορείτε να πάρετε τον κώδικα από το MSDN Code Gallery Σελίδα: Αγωγοί, Φίλτρα, άριστα API και LINQ to SQL .

Απαντήθηκε 07/08/2008 στις 09:22
πηγή χρήστη

ψήφοι
12

Έλυσα αυτό το λίγο διαφορετικά από ό, τι οι άλλοι έχουν ως έπρεπε να κάνω τη δική μου paginator, με ένα αναμεταδότη. Γι 'αυτό και έκανε την πρώτη του μια συλλογή από αριθμούς σελίδων για τη συλλογή των στοιχείων που έχω:

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

Χρησιμοποιώντας αυτό θα μπορούσε εύκολα να στεγανοποιήσει τη συλλογή στοιχείο σε μια συλλογή από «σελίδες». Μια σελίδα στην περίπτωση αυτή είναι απλά μια συλλογή των στοιχείων ( IEnumerable<Item>). Αυτό είναι το πώς μπορείτε να το κάνετε χρησιμοποιώντας Skipκαι Takeσε συνδυασμό με την επιλογή του δείκτη από την pageRangeπαραπάνω δημιουργήθηκε:

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

Φυσικά θα πρέπει να χειριστεί κάθε σελίδα ως πρόσθετη συλλογή, αλλά π.χ. αν φωλιάζουν αναμεταδότες, τότε αυτό είναι πραγματικά εύκολο να χειριστεί.


Το ένα-liner TLDR έκδοση θα είναι η εξής:

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

Που μπορεί να χρησιμοποιηθεί ως εξής:

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

    for (Item item : page) 
    {
        // handle item in page
    }
}
Απαντήθηκε 20/03/2012 στις 13:52
πηγή χρήστη

ψήφοι
9

Αυτή η ερώτηση είναι κάπως παλιά, αλλά ήθελα να δημοσιεύσετε αλγόριθμο σελιδοποίησης μου που δείχνει την όλη διαδικασία (συμπεριλαμβανομένης αλληλεπίδραση του χρήστη).

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

Ωστόσο, εάν είστε μετά από τις επιδόσεις και τον κωδικό παραγωγής, είμαστε όλοι μετά την εκτέλεση, δεν θα πρέπει να χρησιμοποιήσετε τηλεειδοποίησης LINQ, όπως φαίνεται από τα παραπάνω, αλλά το υποκείμενο IEnumeratorγια την εφαρμογή τηλεειδοποίησης τον εαυτό σας. Ως Μάλιστα, είναι τόσο απλό όσο το LINQ-αλγόριθμος που φαίνεται πιο πάνω, αλλά πιο αποδοτικοί:

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

Επεξήγηση: Το μειονέκτημα της χρήσης Skip()για πολλές φορές σε μια «τρόπο με υπερχείλιση» είναι, ότι δεν θα αποθηκεύσει πραγματικά το «δείκτη» της επανάληψης, όπου για τελευταία φορά παραλείπονται. - Αντ 'αυτού η αρχική ακολουθία θα είναι εμπροσθοβαρής με τις κλήσεις παράλειψης, η οποία θα οδηγήσει σε «κατανάλωση» ήδη «καταναλωθεί» σελίδες ξανά και ξανά. - Μπορείτε να αποδείξουν ότι οι ίδιοι, όταν δημιουργείτε την ακολουθία ideasέτσι ώστε να παράγει παρενέργειες. -> Ακόμα κι αν έχουν παραληφθεί 10-20 και 20-30 και θέλετε να επεξεργαστείτε 40+, θα δείτε όλες τις παρενέργειες των 10-30 εκτελούνται και πάλι, πριν ξεκινήσετε την επανάληψη 40+. Η παραλλαγή χρησιμοποιώντας IEnumerableάμεσα «s interface, θα θυμάστε, αντί τη θέση του στο τέλος του περασμένου λογική της σελίδας, έτσι ώστε καμία ρητή παρακάμπτοντας χρειάζεται και ανεπιθύμητη ενέργεια που δεν θα επαναληφθεί.

Απαντήθηκε 16/07/2011 στις 21:07
πηγή χρήστη

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