计算分页列表中要包含的项目数

时间:2019-04-16 14:48:06

标签: c# math pagination

我正在努力解决这个问题,但是我一辈子都做不到!

我正在调用一个分页的API,每个页面有20个项目。我正在尝试在UI上实现无限滚动以使用此API中的数据,并且一次加载12个项目,因此我需要确定我需要从哪个页码中获取该API中要包含的页数。 / p>

例如:

我目前在第10项上,我想再增加20项,这意味着我需要从第1页中拿出10项,然后从第2页中拿出10项。但是我不知道该怎么做!

这是我正在使用的模型:

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)

我将向您展示我已经尝试过的方法,但是这毫无意义,因为我无法确定该怎么做。

一些例子:

currentlyLoaded = 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 个答案:

答案 0 :(得分:2)

第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 result;
}

我没有测试该代码,甚至没有尝试对其进行编译-但这可能会让您有足够的主意以使其正确使用。