具有未知循环数的 Scala 未来

Posted

技术标签:

【中文标题】具有未知循环数的 Scala 未来【英文标题】:Scala future with unknown loop count 【发布时间】:2021-12-07 23:14:52 【问题描述】:

案例是尝试获取评论的子评论列表,通过数据库中的'parentId'字段很容易获得所有子cmet。但是,考虑到可能的长列表,最好对数据库查询进行分页。我们可以像这样获取指定的行:


  def getChildCommentsByParentId(parentId: Int, offset: Int, rows: Int): Future[Seq[CommentsRow]] = 
    val query = Comments.filter(row => row.iparentid === parentId && row.istatus === statusNormal ).drop(offset).take(rows)
    db.run(query.result)
  

对于通过多次调用固定页面大小的分页来获取所有行,很容易在其他编程语言中以迭代方式表达这一点,如下所示:

           $replyList = [];
           do 
               $ret = getChildCommentsByParentId(parentId, page * pagesize, pagesize);
               if (!empty($ret)) 
                   $replyList = array_merge($replyList, $ret);
               
               if (count($ret) < $pageSize) 
                   break;
               
               $page ++ ;
            while(true);

在scala中使用理解来处理多个期货是合理的,但我不知道如何处理这种情况。关键是,当前迭代依赖于前一个('page'参数),当行数小于pagesize时,返回包含所有前数据行的完整结果。

谢谢!

【问题讨论】:

那是 php 吗?那段代码中的执行行为是什么?我认为它是顺序的。您首先必须决定是否希望对 DB 的多个调用按顺序或同时执行。前者性能不高,后者有点棘手 是的,它是 php...我正在用 scala 替换 php,但现在我发现 scala 的未来远不如 php 的协程友好,因为你必须以嵌套方式调用 db . 执行行为是顺序的。它应该取决于先前的数据库分页调用来决定是否调用下一页数据。 @sinanspd 如果您不习惯组合编程,可能会觉得不友好。无论如何,为什么不直接定义一个递归函数呢?一旦主体中的未来解决了,它将对同一函数进行回调,直到您需要停止 我尝试用递归的方式解决,请在答案中查看。我只是写了它,还没有测试它,可能有错误。 @sinanspd 【参考方案1】:

我尝试用递归的方式解决它:

  def getChildComments(nextPage: Int, commentId: Int) : Future[CommentResult] = 

    val pageSize = 5

    val currentPageFuture = commentModel.getChildCommentsByParentId(commentId, nextPage*pageSize, pageSize).map 
      data => CommentResult(nextPage, data)
    

    val nextPageFuture = currentPageFuture.flatMap( commentRes =>
      val nextPage = commentRes.nextPage+1
      if(commentRes.data.size >= pageSize) 
        getChildComments(nextPage, commentId)
      
      else 
        Future.successful(CommentResult(nextPage, Seq()))
      
    )

    for 
      currentPageComments <- currentPageFuture
      nextPageComments <- nextPageFuture
     yield 
      CommentResult(currentPageComments.nextPage, currentPageComments.data ++ nextPageComments.data)
    
  

  case class CommentResult(nextPage: Int, data: Seq[TbcommentsRow])

但还是觉得丑,不知道有没有更优雅的方式?

【讨论】:

this 这样的东西怎么样?你可以用你的大小逻辑替换Option 供参考 @LuisMiguelMejíaSuárez 更像我的意思。 谢谢兄弟。它更加简洁明了。但是如果要将所有结果组合成一个大序列,还需要更多的努力。 @LuisMiguelMejíaSuárez @BugSource 我真的不明白这有什么意义......但无论如何,你会这样做:scastie.scala-lang.org/BalmungSan/d8zSwmunRU6HLMMOnunlgg/3 太棒了!学到了很多。 @LuisMiguelMejíaSuárez

以上是关于具有未知循环数的 Scala 未来的主要内容,如果未能解决你的问题,请参考以下文章

具有未知默认参数的 Scala 函数调用

好程序员大数据学习路线分享Scala分支和循环

将具有未知列数的数据导入R?

如何在C中声明具有两列和未知行数的矩阵

解析具有未知列数的 Pandas 数据框以在 statsmodels.api 中使用

就是个控制结构,Scala能有什么新花样呢?