ПЕЙДЖИНГ коллекции с помощью 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

Несколько месяцев назад я написал в блоге о Fluent Интерфейсах и LINQ , который использовал метод расширения IQueryable<T>и другой класс , чтобы обеспечить следующий естественный способ постраничной коллекции LINQ.

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

Вы можете получить код из MSDN Code Gallery Страницы: Трубопроводы, Фильтры, Fluent API и LINQ к 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));

Конечно, вы должны обрабатывать каждую страницу в качестве дополнительного сбора, но, например, если вы вложенности ретрансляторов, то это на самом деле прост в обращении.


Один вкладыш 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 напрямую, вместо этого помнить положение конца последней логической страницы, поэтому нет явного пропуска не требуется , а побочные эффекты не будут повторяться.

Ответил 16/07/2011 в 21:07
источник пользователем

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