【问题标题】:Working out how many items to take in a paginated list计算分页列表中要包含多少项目
【发布时间】:2019-09-06 17:18:54
【问题描述】:

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

我正在调用一个分页的 API,每个页面有 20 个项目。我正在尝试在我的 UI 上实现无限滚动以使用来自此 API 的数据,并且我们一次加载 12 个项目,因此我需要计算出我需要从中获取的页码以及从该 API 中获取的页码。

例如:

我目前在第 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");
    }
}

【问题讨论】:

    标签: c# math pagination


    【解决方案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 &gt; 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;
    }
    

    我没有测试这段代码,甚至没有尝试编译它——但这可能会给你足够的想法来让它正确。

    【讨论】:

    • @JamieRees 我会尝试添加一些 C# :)
    • 非常感谢您的帮助,这让我走上了正确的轨道:)
    猜你喜欢
    • 2019-09-06
    • 2018-05-04
    • 2019-10-02
    • 2023-01-22
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多