小编Raj*_*j B的帖子

建议在多个值上优化简单的Scala foldLeft?

我正在重新实现一些从Java到Scala的代码(一种简单的贝叶斯推理算法,但这并不重要).我希望以尽可能最高效的方式实现它,同时通过尽可能避免可变性来保持代码的清洁和功能.

以下是Java代码的片段:

    // initialize
    double lP  = Math.log(prior);
    double lPC = Math.log(1-prior);

    // accumulate probabilities from each annotation object into lP and lPC
    for (Annotation annotation : annotations) {
        float prob = annotation.getProbability();
        if (isValidProbability(prob)) {
            lP  += logProb(prob);
            lPC += logProb(1 - prob);
        }
    } 
Run Code Online (Sandbox Code Playgroud)

很简单吧?所以我决定在第一次尝试时使用Scala foldLeft和map方法.由于我有两个值,我正在积累,累加器是一个元组:

    val initial  = (math.log(prior), math.log(1-prior))
    val probs    = annotations map (_.getProbability)
    val (lP,lPC) = probs.foldLeft(initial) ((r,p) => {
      if(isValidProbability(p)) (r._1 + logProb(p), r._2 + logProb(1-p)) else r
    })
Run Code Online (Sandbox Code Playgroud)

不幸的是,这段代码的执行速度比Java快5倍(使用简单且不精确的度量标准;只需在循环中调用代码10000次).一个缺点很明显; 我们遍历列表两次,一次是在map中调用,另一次是在foldLeft中.所以这是一个遍历列表的版本.

    val (lP,lPC) …
Run Code Online (Sandbox Code Playgroud)

optimization functional-programming scala fold

5
推荐指数
1
解决办法
1341
查看次数