“消费”;页码为“;(不完全是)Scala中具有未知页面计数和未知页面大小的API
假设您使用的API最多提供100个元素,并允许您获取更多元素,而不是通过指定页码,而是通过告诉它您收到的最后一个元素。然后,您可能希望对这种准分页进行抽象。 在Scala你会怎么做 我提出了一段可能有错误(=未经过彻底测试)且非常有状态的代码:“消费”;页码为“;(不完全是)Scala中具有未知页面计数和未知页面大小的API,scala,pagination,discord,Scala,Pagination,Discord,假设您使用的API最多提供100个元素,并允许您获取更多元素,而不是通过指定页码,而是通过告诉它您收到的最后一个元素。然后,您可能希望对这种准分页进行抽象。 在Scala你会怎么做 我提出了一段可能有错误(=未经过彻底测试)且非常有状态的代码: 抽象类迭代器ATKEEPSONGIVING[T]扩展迭代器[T]{ 私有变量currentIter:迭代器[T]=_ 私有变量currentElement:T=_ def nextIterator(lastElement:选项[T]):迭代器[T] fe
抽象类迭代器ATKEEPSONGIVING[T]扩展迭代器[T]{
私有变量currentIter:迭代器[T]=_
私有变量currentElement:T=_
def nextIterator(lastElement:选项[T]):迭代器[T]
fetchNewBatch(无)
def fetchNewBatch(lastElement:Option[T])={
currentIter=nextIterator(最后一个元素)
}
def hasNext:Boolean=currentIter.hasNext | |{
fetchNewBatch(Some(currentElement))
哈斯奈特
}
def next():T={
currentIter.nextOption()匹配{
案例部分(值)=>
currentElement=值
价值
案例无=>
fetchNewBatch(Some(currentElement))
下一个()
}
}
}
我不喜欢它
使用:
val numberIterator=new迭代器atkeepsonging[Int]{
def nextIterator(lastElement:Option[Int]):迭代器[Int]={
val i=lastElement.getOrElse(-1)
((i+1)到(i+4))。迭代器
}
}
一定有更好的办法。当然,我不是第一个被这种分页方式困扰的人。这个词的正确名称是什么?我该如何抽象它呢
所讨论的API是Discord的消息列表API:
考虑的备选方案
我发现了这个问题:
但是,在我的例子中,我没有总页数。
这个答案还假设页面大小是恒定的,虽然在我的例子中给出了这一点,但我更喜欢只知道“我得到的最后一个元素是X。我如何得到一些更多元素?”而不是“我上一次得到X,我如何得到下一个Y元素?”的解决方案。此外,这是无关的,因为我不能直接指定页码
Akka溪流中也有同样问题的
flatMapConcat
(和mapConcat
)。。。它看起来更好/更聪明,但在迭代时将整个页面的元素保留在内存中,而不是一次只保留一个(这可能很好,因为分页器已经保存了对它们的引用)
嗯,你可以这样做。。。它看起来更好/更聪明,但在迭代时将整个页面的元素保留在内存中,而不是一次只保留一个(这可能很好,因为分页器已经保存了对它们的引用)
非常有趣<代码>迭代!这就是它的名字。我记得在标准图书馆里有类似的东西,但我很快就停止了寻找。很高兴看到有一个版本提供了以前的值。这非常有帮助!“懒散列表”的原因是什么?你就不能这样做:
val iter:Iterator[Seq[Msg]]=Iterator.iterate(nextBatchOfMessages(None))(lastList=>nextBatchOfMessages(lastList.lastpoption));val iter2:Iterator[Msg]=iter.flatMap(u.Iterator)
?我不知道你的nextBatch
返回什么。我不想把它限制在IterableOnce
之外。还有.flatMap(uu.iterator)
=.flatten
。您确实需要takeWhile
,因为如果没有它,您只需在完成后重新开始。这是一个很好的答案,它正好利用了为此而创建的功能。从文档:def iterate[T](开始:T)(f:(T)=>T):迭代器[T]创建一个无限迭代器,该迭代器将给定的函数重复应用于先前的结果代码>非常有趣<代码>迭代
!这就是它的名字。我记得在标准图书馆里有类似的东西,但我很快就停止了寻找。很高兴看到有一个版本提供了以前的值。这非常有帮助!“懒散列表”的原因是什么?你就不能这样做:val iter:Iterator[Seq[Msg]]=Iterator.iterate(nextBatchOfMessages(None))(lastList=>nextBatchOfMessages(lastList.lastpoption));val iter2:Iterator[Msg]=iter.flatMap(u.Iterator)
?我不知道你的nextBatch
返回什么。我不想把它限制在IterableOnce
之外。还有.flatMap(uu.iterator)
=.flatten
。您确实需要takeWhile
,因为如果没有它,您只需在完成后重新开始。这是一个很好的答案,它正好利用了为此而创建的功能。从文档:def iterate[T](开始:T)(f:(T)=>T):迭代器[T]创建一个无限迭代器,该迭代器将给定的函数重复应用于先前的结果
fwiw I对上述迭代器做了一个稍微改进和稍微测试的版本:fwiw I对上述迭代器做了稍微改进和稍微测试的版本:
Iterator
.iterate(fetchNewBatch(None).to(LazyList)) {
fetchNewBatch(_.lastOption).to(LazyList)
}.takeWhile(_.nonEmpty)
.flatten