Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当skip不能被take整除时,通过pageIndex/pageSize分页实现skip/take分页_C#_Pagination_Ienumerable - Fatal编程技术网

C# 当skip不能被take整除时,通过pageIndex/pageSize分页实现skip/take分页

C# 当skip不能被take整除时,通过pageIndex/pageSize分页实现skip/take分页,c#,pagination,ienumerable,C#,Pagination,Ienumerable,假设我有一个神奇的分页黑盒类,它使用pageIndex和pageSize检索数据,如下所示: public class PaginatedList<T> { // ... // Chops up the internally stored list into pages of size "pageSize", // then returns the page stored at index "pageIndex". public IEnumerabl

假设我有一个神奇的分页黑盒类,它使用
pageIndex
pageSize
检索数据,如下所示:

public class PaginatedList<T>
{
    // ...

    // Chops up the internally stored list into pages of size "pageSize",
    // then returns the page stored at index "pageIndex".
    public IEnumerable<T> Get(int pageIndex, int pageSize)
    {
        // Magic black box code goes here.
    }

    // ...
}
但是,如果我想跳过的偏移量不能被我想获取的量整除,我还能如何高效地实现
OffsetGet(myList,skip,take)
(也就是说,不需要进行多个
Get(pageIndex,pageSize)
调用)


如果这个问题已经在某个地方得到了回答,或者如果上面的代码太模糊,则表示歉意;这是我关于StackOverflow的第一个问题,所以请温柔点。=]

您可以直接使用LINQ的Skip和Take方法

return mylist.Skip(skip).Take(take).AsEnumerable();

这部分取决于您希望在代码复杂性和数据获取效率之间取得多大的平衡

通过获取所需数据的两倍,您始终可以成功:

int virtualTake = take * 2;
int virtualSkip = skip / virtualTake;
var bigList = Get(myList, virtualSkip / virtualTake, virtualTake);
int offset = virtualSkip % take;
var pruned = bigList.Skip(offset).Take(take);
然而,在许多情况下,这将获取比您需要的更多的数据。对于
skip
已经是
take
的倍数的情况,您至少可以进行优化,但对于其他情况,您可以进行改进

例如,如果您想跳过23并取5,则上述操作将有效地跳过20并取10,然后删除。。。但你可以跳过21,改为7。代码基于astander在以下评论中的建议:

int newTake = take;
while ((skip / newTake + 1) * newTake < (skip + take))
{
     newTake++;
}
var bigList = Get(myList, skip / newTake, newTake);
int offset = skip % newTake;
var pruned = bigList.Skip(offset).Take(take);
int newTake=take;
而((跳转/跳转+1)*跳转<(跳转+跳转))
{
newTake++;
}
var bigList=Get(myList,skip/newTake,newTake);
int offset=跳过%newTake;
var pruned=bigList.Skip(offset).Take(Take);

我想你没有抓住问题的重点。OP只能访问
Get
方法,并且想要计算出要传递的参数。问得好。我想知道这是否只是找到GCD的问题,但并不是那么简单。。。你有多在乎只获取最小数量的数据?另外,页面索引是基于零还是基于1?@JonSkeet谢谢。我不太在乎我们是否最终获取了一些额外的记录,然后删减了结果;主要的瓶颈是
Get
调用,它不应该被多次调用。@astander-Hmm,实际上我不确定。我怀疑它必须是基于零的,因为
OffsetGet(myList,20,5)
应该与
Get(4,5)
等效。不过,我可能会犯一些一个接一个的错误。您可以随意将索引更改为任何适合您的内容;而((跳转/跳转+1)*跳转<(跳转+跳转))跳转++;int newSkip=(跳过/newTake)*newTake我对几个窗口进行了测试,它似乎按照预期工作,返回最小窗口大小以重叠
take
size@astander:是的,那很好。对于非常大的
take
,它的效率可能低于过度抓取-但这实际上取决于我们不知道的事情。介意我在回答中加上那个密码吗?(或者你也可以创建自己的答案,当然……)请继续并将其添加到答案中。@astander:完成。我想我已经对它进行了适当的调整:)
int newTake = take;
while ((skip / newTake + 1) * newTake < (skip + take))
{
     newTake++;
}
var bigList = Get(myList, skip / newTake, newTake);
int offset = skip % newTake;
var pruned = bigList.Skip(offset).Take(take);