Определение количества элементов в разбитом на страницы списке

#c# #math #pagination

#c# #математика #разбивка на страницы

Вопрос:

Я пытаюсь разобраться с этим, но ни за что на свете не могу!

Я вызываю разбитый на страницы API, каждая страница содержит 20 элементов. Я пытаюсь реализовать бесконечную прокрутку в своем пользовательском интерфейсе, чтобы использовать данные из этого API, и мы загружаем 12 элементов одновременно, поэтому мне нужно определить, с какого номера страницы мне нужно взять и сколько взять в этом API.

Например:

В настоящее время я нахожусь на пункте 10, и я хочу взять еще 20 элементов, это означает, что мне нужно взять 10 элементов со страницы 1, а затем 10 элементов со страницы 2. Но я не могу понять, как это сделать!

Это модель, с которой я работаю:

 public class PagesToLoad
{
    public int Page { get; set; }
    public int Take { get; set; }
    public int Skip { get; set; }
}
 

Вот сигнатура метода

 public static List<PagesToLoad> GetPage(int currentlyLoaded, int toLoad, int maxItemsPerPage)
 

Я бы показал вам, что я пробовал, но это бессмысленно, поскольку я не могу понять, как это сделать.

Несколько примеров:

currentlyGoaded = 0, и я хочу загрузить 12, а значение maxItemsPerPage равно 20. Итак, результаты должны быть:

 new List<PagesToLoad>
{
    new PagesToLoad
    {
        Page = 1,
        Skip = 0,
        Take = 12
    },
}
 

currentlyLoaded = 10, и я хочу загрузить 20, а значение maxItemsPerPage равно 20.
Итак, результаты должны быть:

 new List<PagesToLoad>
{
    new PagesToLoad
    {
        Page = 1,
        Skip = 10,
        Take = 10
    },
    new PagesToLoad
    {
        Page = 2,
        Take = 10,
        Skip = 0
    }
}
 

Обновить:

Я написал несколько модульных тестов, чтобы попытаться протестировать некоторые из этих сценариев с использованием NUnit. Приведенные ниже тесты в настоящее время проверяют только то, что он возвращает правильную страницу, с которой мы должны брать, и в настоящее время не проверяет правильную позицию на текущей странице

 [TestCaseSource(nameof(TestData))]
public void TestPaginationPagesToLoad(int currentlyLoaded, int toLoad, int maxItemsPerPage, int[] expectedPages)
{
    var result = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, maxItemsPerPage);
    var pages = result.Select(x => x.Page).ToArray();

    Assert.That(pages.Length, Is.EqualTo(expectedPages.Length), "Did not contain the correct amount of pages");
    for (int i = 0; i < pages.Length; i  )
    {
        Assert.That(pages[i], Is.EqualTo(expectedPages[i]));
    }


}

public static IEnumerable<TestCaseData> TestData
{
    get
    {

            yield return new TestCaseData(0, 10, 20,  new [] { 1 }).SetName("Load_First_Page");
            yield return new TestCaseData(20, 10, 20, new [] { 2 }).SetName("Load_Second_Page");
            yield return new TestCaseData(0, 20, 20,  new [] { 1 }).SetName("Load_Full_First_Page");
            yield return new TestCaseData(20, 20, 20, new [] { 2 }).SetName("Load_Full_Second_Page");
            yield return new TestCaseData(10, 20, 20, new [] { 1, 2 }).SetName("Load_Half_First_Page_And_Half_Second_Page");
            yield return new TestCaseData(19, 20, 20, new [] { 1, 2 }).SetName("Load_End_First_Page_And_Most_Second_Page");
    }
}
 

Ответ №1:

Страница n содержит элементы (от sn — s 1) до sn включительно с обоих концов, где s — количество элементов на странице. Предположим, вы находитесь в пункте m и хотите взять еще k элементов. Затем вы хотите взять элементы m 1, m 2, …, m k. Первая страница, на которую вам нужно посмотреть, — это (m 1 — 1) / s 1, где деление — это целочисленное деление (только частное, без остатка). На этой странице вам нужно начать брать с (m 1 — 1) % s 1 и далее, где % — остаток после деления (по модулю). Последняя страница, на которую вам нужно будет посмотреть, — это (m k — 1) / s 1, и вам нужно будет посмотреть до (m k — 1) % s 1 .

Ваш пример:

 s = 20
m = 10
k = 20
first page:   (m   1 - 1) / s   1
            = (10   1 - 1) / 20   1
            = 10 / 20   1
            = 0   1 = 1


start pos:    (m   1 - 1) % s   1
            = (10   1 - 1) % 20   1
            = 10 % 20   1
            = 10   1 = 11

last page:    (m   k - 1) / s   1
            = (10   20 - 1) / 20   1
            = 29/20   1
            = 1   1 = 2


stop pos:     (m   k - 1) % s   1
            = (10   20 - 1) % 20   1
            = 29 % 20   1
            = 9   1 = 10
 

Обратите внимание, что если last page > first page 1 вам нужно получить все промежуточные страницы.

РЕДАКТИРОВАТЬ: добавление некоторого C # может даже сработать!

 List<PagesToLoad> GetPagesToload(int curItemIndex, int numItemsToGet, int itemsPerPage)
{
    List<PagesToLoad> result = new List<pagesToLoad>();

    int firstPage = curItemIndex / itemsPerPage   1;
    int startPos = curItemIndex % itemsPerPage   1;

    int lastItemIndex = curItemIndex   numItemsToGet - 1;
    int lastPage = lastItemIndex / itemsPerPage   1;
    int stopPos = lastItemIndex % itemsPerPage   1;

    PagesToLoad page1 = new PagesToLoad();
    page1.Page = firstPage;
    page1.Skip = curItemIndex;
    page1.Take = numItemsToGet;

    if (numItemsToGet   startPos - 1 > itemsPerPage)
    {
        page1.Take = itemsPerPage - startPos   1;
        result.Add(page1);

        for (int i = firstPage   1; i < lastPage; i  )
        {
            PagesToAdd nextPage = new PagesToAdd();
            nextPage.Page = i;
            nextPage.Skip = 0;
            nextPage.Take = itemsPerPage;
            result.Add(nextPage);
        }

        PagesToAdd pageN = new PagesToAdd();
        pageN.Page = lastPage;
        pageN.Skip = 0;
        pageN.Take = stopPos;
        result.Add(pageN);
    }
    else
    {
        result.Add(page1);
    }

    return resu<
}
 

Я не тестировал этот код и даже не пытался его скомпилировать, но это может дать вам представление о том, как все сделать правильно.

Комментарии:

1. @JamieRees Я постараюсь добавить немного C # 🙂

2. Большое спасибо за помощь, которая навела меня на правильный путь 🙂