首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >foldLeft的优化

foldLeft的优化
EN

Stack Overflow用户
提问于 2021-01-22 09:50:20
回答 2查看 152关注 0票数 1

我正在使用下面的代码,我正在寻找一些想法来进行一些优化。

analyzePayload:

输入:有效负载,即JsObject和规则列表,每个规则都有几个条件。

输出:在此特定负载上成功、notApplicable或失败的所有规则的 MyReport

列表的大小可以是相当大的,而且每个规则都有大量的条件。

我正在寻找一些关于如何优化代码的想法,也许是用一个懒惰的集合?视野?溪流?裁缝?为什么-谢谢!

另外,请注意,我有anaylzeMode,它只能在一条规则对ex成功之前才能运行。

代码语言:javascript
复制
def analyzePayload(payload: JsObject, rules: List[Rule]): MyReport = {
    val analyzeMode = appConfig.analyzeMode
    val (succeed, notApplicable, failed) = rules.foldLeft((List[Rule](), List[Rule](), List[Rule]())) { case ( seed @ (succeedRules,notApplicableRules,failedRules), currRule) =>

      // Evaluate Single Rule
      def step(): (List[Rule], List[Rule], List[Rule]) = evalService.eval(currRule, payload) match {

        // If the result is succeed
        case EvalResult(true, _, _) => (currRule :: succeedRules, notApplicableRules, failedRules)

        // If the result is notApplicable 
        case EvalResult(_, missing @ _ :: _, _) => (succeedRules, currRule :: notApplicableRules, failedRules
        )

        // If the result is unmatched
        case EvalResult(_, _, unmatched @ _ :: _) => (succeedRules, notApplicableRules, currRule :: failedRules)
      }

      analyzeMode match {
        case UNTIL_FIRST_SUCCEED => if(succeedRules.isEmpty) step() else seed
        case UNTIL_FIRST_NOT_APPLICABLE => if(notApplicableRules.isEmpty) step() else seed
        case UNTIL_FIRST_FAILED => if(failedRules.isEmpty) step() else seed
        case DEFAULT => step()
        case _ => throw new IllegalArgumentException(s"Unknown mode = ${analyzeMode}")
      }
    }

    MyReport(succeed.reverse, notApplicable.reverse, failed.reverse)
  }

第一编辑:修改了代码以使用tailrec,从@Tim,还有其他建议吗?或者一些让代码更漂亮的建议?另外,我想问一下,在前面的实现中,在view之前使用foldLeft是否有什么不同。也可以使用其他集合,如ListBufferVector

代码语言:javascript
复制
  def analyzePayload(payload: JsObject, actionRules: List[ActionRule]): MyReport = {
    val analyzeMode = appConfig.analyzeMode

    def isCompleted(succeed: List[Rule], notApplicable: List[Rule], failed: List[Rule]) = ((succeed, notApplicable, failed), analyzeMode) match {
      case (( _ :: _, _, _), UNTIL_FIRST_SUCCEED) | (( _,_ :: _, _), UNTIL_FIRST_NOT_APPLICABLE) | (( _, _, _ :: _), UNTIL_FIRST_FAILED) => true
      case (_, DEFAULT) => false
      case _ => throw new IllegalArgumentException(s"Unknown mode on analyzePayload with mode = ${analyzeMode}")
    }

    @tailrec
    def _analyzePayload(actionRules: List[ActionRule])(succeed: List[Rule], notApplicable: List[Rule], failed: List[Rule]): (List[Rule], List[Rule] ,List[Rule]) = actionRules match {
      case Nil | _ if isCompleted(succeed, notApplicable, failed) => (succeed, notApplicable, failed)
      case actionRule :: tail => actionRuleService.eval(actionRule, payload) match {
        // If the result is succeed
        case EvalResult(true, _, _) => _analyzePayload(tail)(actionRule :: succeed, notApplicable, failed)

        // If the result is notApplicable
        case EvalResult(_, missing @ _ :: _, _) => _analyzePayload(tail)(succeed, actionRule :: notApplicable, failed)

        // If the result is unmatched
        case EvalResult(_, _, unmatched @ _ :: _) => _analyzePayload(tail)(succeed, notApplicable, actionRule :: failed)
      }
    }

    val res = _analyzePayload(actionRules)(Nil,Nil,Nil)
    MyReport(res._1, res._2, res._3)
  }

编辑2:(问题)

如果有结果,

  1. 会转发给客户端--作为view,这样做没有意义吗?既然所有的数据都将被评估,对吗?

  1. ,也许我应该使用ParSeq来代替?或者这只是慢一点,因为evalService.eval(...)的操作不是一个繁重的操作??
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-22 11:10:31

有两个明显的优化:

使用尾递归函数评价器而不是foldLeft,这样编译器就可以生成一个优化的循环,并在找到合适的规则后立即终止。

由于analyzeMode是常量,所以将match取到foldLeft之外。或者为每种模式都有单独的代码路径,或者使用analyzeMode来选择循环中使用的函数来检查是否终止。

票数 2
EN

Stack Overflow用户

发布于 2021-01-22 12:10:08

代码很好,重温的主要内容是让evalService.eval在json对象的单个遍历中计算多条规则,前提是json的大小不可忽略。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65842837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档