在Scala中执行结果分页的更好方法
我经常进行结果分页(给定一个页码和一个页面大小来计算起始、结束和总页面),我从Java移植了这个小函数来帮助:在Scala中执行结果分页的更好方法,scala,pagination,paging,Scala,Pagination,Paging,我经常进行结果分页(给定一个页码和一个页面大小来计算起始、结束和总页面),我从Java移植了这个小函数来帮助: def page(page: Int, pageSize: Int, totalItems: Int) = { val from = ((page - 1) * pageSize) + 1 var to = from + pageSize - 1 if (to > totalItems) to = totalItems var totalPages
def page(page: Int, pageSize: Int, totalItems: Int) = {
val from = ((page - 1) * pageSize) + 1
var to = from + pageSize - 1
if (to > totalItems) to = totalItems
var totalPages: Int = totalItems / pageSize
if (totalItems % pageSize > 0) totalPages += 1
(from, to, totalPages)
}
在接受方:
val (from, to, totalPages) = page(page, pageSize, totalItems)
虽然它可以工作,但我确信在Scala中有更多可读性和功能性的方法来做同样的事情。什么是更像scala的方法
特别是,我试图找到一种更好的表达方式:
var to = from + pageSize - 1
if (to > totalItems) to = totalItems
在Java中,我可以执行以下操作:
from + pageSize - 1 + (to > totalItems) ? 1 : 0;
最简单的改进是只使用函数而不是变量(并避免用参数名隐藏方法名,因此无论是否调用递归函数都更清晰):
关键的变化只是使用
min
函数而不是单独的变量,并让if
语句返回0或1,而不是让它更新变量。问题的一半是识别模式:
def pageCalc(page: Int, pageSize: Int, totalItems: Int) = {
val pages = 1 to totalItems by pageSize
val from = pages(page - 1)
val to = from + pageSize - 1 min totalItems
val totalPages = pages.size
(from, to, totalPages)
}
不过,真的,也许你可以直接使用
范围
?谢谢雷克斯。我同意函数名的更改。我只是很快地把一些东西拼凑起来,以确保它被编译。我认为“min”是一个明显的改进,“if”解决了var的使用问题。如果有更简洁的东西,那会更好在Java中。@Ike-没有内置的三元运算符,但是您可以很容易地定义自己的运算符。比如说,我看到了。非常有趣的帖子。对于“相对较少”的收益来说,这似乎是一个过于复杂的解决方案(甚至不考虑评论中提出的性能影响)。我认为你提出的上述修改达到了正确的平衡。再次感谢。顺便说一句,在我将代码简化为与开始时几乎相同的内容之前,由于一些简单的错误,我对代码进行了大量的编辑,这让我印象深刻。谢谢Daniel。我不知道射程中的“by”。这里有一个有趣的应用程序。我们通过创建一个巧妙的集合来避免一些算术运算。我想这是品味的问题。不确定大量totalItems的性能影响和可伸缩性考虑因素,但我认为这些因素与此的大多数实际用途无关。@实际上,所有算术运算都隐藏在范围内。当我做pages(第1页)
时,它所做的计算与您和Rex所做的几乎相同——因此,具有几乎相同的性能。事实上,Range
可能是Scala中最优化的集合。不管怎样,主要的优点是你不需要“解码”算法来理解代码。第二个主要优点是减少了出现bug的机会。
def pageCalc(page: Int, pageSize: Int, totalItems: Int) = {
val pages = 1 to totalItems by pageSize
val from = pages(page - 1)
val to = from + pageSize - 1 min totalItems
val totalPages = pages.size
(from, to, totalPages)
}