Aquí podría ser tu PUBLICIDAD


Localizar una colección con LINQ

votos
69

¿Cómo pagina a través de una colección en LINQ dado que tiene a startIndexy a count?

Publicado el 01/08/2008 a las 14:20
fuente por usuario Nick Berardi
En otros idiomas...        العربية       

4 respuestas

votos
61

Es muy simple con los métodos de extensión Skipy Take.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);
Respondida el 01/08/2008 a las 02:22
fuente por usuario Nick Berardi


Aquí podría ser tu PUBLICIDAD


votos
38

Hace unos meses, escribí una entrada en el blog sobre Fluent Interfaces y LINQ que utilizaba un Método de extensión en IQueryable<T>y otra clase para proporcionar la siguiente forma natural de paginar una colección LINQ.

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

Puede obtener el código de la página MSDN Code Gallery: Pipelines, Filters, Fluent API y LINQ to SQL .

Respondida el 07/08/2008 a las 09:22
fuente por usuario Mike Minutillo

votos
12

He resuelto esto un poco diferente de lo que los otros tienen ya que tuve que hacer mi propia paginador, con un repetidor. Así que hice por primera vez una colección de números de página para la colección de artículos que tengo:

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

El uso de este podría fácilmente dividir el punto de recogida en una colección de "páginas". Una página en este caso es sólo una colección de artículos ( IEnumerable<Item>). Esta es la forma en que puede hacerlo utilizando Skipy Take, junto con la selección del índice de la pageRangecreada anteriormente:

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

Por supuesto, usted tiene que manejar cada página como una colección, pero por ejemplo, si usted está anidando repetidores, entonces esto es realmente fácil de manejar.


La de una sola línea TLDR versión sería la siguiente:

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

Que puede ser utilizado como esto:

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

    for (Item item : page) 
    {
        // handle item in page
    }
}
Respondida el 20/03/2012 a las 01:52
fuente por usuario Spoike

votos
9

Esta pregunta es un poco viejo, pero quería publicar mi algoritmo de paginación que muestra todo el procedimiento (incluyendo la interacción del usuario).

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

Sin embargo, si usted está después de la actuación, y en el código de producción, estamos todos después de la actuación, no se debe utilizar paginación de LINQ como se muestra arriba, sino más bien el subyacente IEnumeratora implementar la paginación mismo. Como cuestión de hecho, es tan simple como el LINQ algoritmo que se muestra arriba, pero con más prestaciones:

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

Explicación: La desventaja de usar Skip()para múltiples veces en un "modo de cascada" es, que no va a almacenar en realidad el "puntero" de la iteración, donde se ha omitido pasado. - En lugar de la secuencia original será de carga frontal con llamadas de salto, lo que conducirá a "consumir" las páginas ya "consumido" una y otra vez. - Se puede demostrar que usted mismo, cuando se crea la secuencia ideasde modo que produce efectos secundarios. -> Incluso si se ha saltado 10-20 y 20-30 y quiere procesar 40+, verá todos los efectos secundarios de 10-30 que se está ejecutando de nuevo, antes de empezar la iteración 40+. La variante utilizando IEnumerablela interfaz 's directamente, en su lugar recordar la posición del final de la última página lógica, por lo que no se necesita saltar explícito y no se repetirá efectos secundarios.

Respondida el 16/07/2011 a las 09:07
fuente por usuario Nico