繁体   English   中英

快速功能等效于For Loop Scala

[英]Fast Functional Equivalent Of For Loop Scala

我在Scala中有以下两个代码段:

/* Iterative */   
for (i <- max to sum by min) {
  if (sum % i == 0) validBusSize(i, L, 0)
}

/* Functional */
List.range(max, sum + 1, min)
    .filter(sum % _ == 0)
    .map(validBusSize(_, L, 0))

这两个代码段都是其他相同对象的一部分。 但是,当我在Hackerrank上运行代码时,带有迭代代码段的对象最多花费1.45秒,而功能代码段导致代码花费> 7秒,这是超时。

我想知道是否可以在保持速度的同时在功能上重写for循环。 我看了看Stream容器,但是我还是不得不在map之前调用filter ,而不是依次计算每个有效的validBusSize

谢谢!

编辑:

/* Full Code */
import scala.io.StdIn.readLine

object BusStation {

  def main(args: Array[String]) {

    readLine
    val L = readLine.split(" ").map(_.toInt).toList

    val min = L.min
    val max = L.max
    val sum = L.foldRight(0)(_ + _)

    /* code under consideration */
    for (i <- max to sum by min) {
      if (sum % i == 0) validBusSize(i, L, 0)
    }
  }

  def validBusSize(size: Int, L: List[Int], curr: Int) {

    L match {        
      case Nil if (curr == size) => print(size + " ") 
      case head::tail if (curr < size) => 
        validBusSize(size, tail, curr + head)
      case head::tail if (curr == size) => validBusSize(size, tail, head)
      case head::tail if (curr > size) => return
    }
  }
}

现在,对快速功能代码最好的选择是尾递归函数:

@annotation.tailrec
def getBusSizes(i: Int, sum: Int, step: Int) {
  if (i <= sum) {
    if (sum % i == 0) validBusSize(i, L, 0)
    getBusSizes(i + step, sum, step)
  }
}

各种其他事情都会很快,但是对于像这样的事情,大多数是简单的数学运算,通用接口的开销将是可观的。 使用尾递归功能,您将在下面获得while循环。 (您不需要注释使它成为尾递归;这只会导致编译失败,否则会失败。无论是否存在注释,都会进行优化。)

因此,显然以下工作:

用Range对象替换List.range(max, sum + 1, min) (max to sum by min) 还要问另一个问题,为什么会这样。

考虑将范围转换为带有关键字par的并行版本,例如这样

(max to sum by min).par

这可能会提高性能,尤其是对于在调用validBusSize具有较大值的较大范围的validBusSize

因此,在拟议的理解中,

for ( i <- (max to sum by min).par ) {
  if (sum % i == 0) validBusSize(i, L, 0)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM