使用List作为累加器的折叠方法

时间:2016-05-05 11:04:41

标签: scala

要查找数字的素数因子我正在使用这段代码:

 def primeFactors(num: Long): List[Long] = {
   val exists = (2L to math.sqrt(num).toLong).find(num % _ == 0)
    exists match {
     case Some(d) => d :: primeFactors(num/d)
     case None => List(num)
  }
}

但是我找到了一个很酷且功能更强的方法来解决这个问题:

def factors(n: Long): List[Long] = (2 to math.sqrt(n).toInt)
.find(n % _ == 0).fold(List(n)) ( i => i.toLong :: factors(n / i)) 

之前我使用foldLeftfold只是为了获得列表或其他简单计算的总和,但在这里我似乎无法理解折叠是如何工作的以及它是如何突破的递归函数。有人可以解释折叠功能在这里是如何工作的。

1 个答案:

答案 0 :(得分:4)

选项fold

如果查看Option fold函数的签名,则需要两个参数:

def fold[B](ifEmpty: => B)(f: A => B): B

它的作用是,如果f不为空,它会对Option应用Option。如果ifEmpty为空,则只返回i => i.toLong :: factors(n / i)的输出(这是递归的终止条件)。

因此,在您的情况下,f代表Option,如果List(n)不为空,则会对其进行评估。虽然fold是终止条件。

fold用于收集/迭代器

您收集的其他def foldLeft[B](z: B)(op: (B, A) => B): B 来自TraversableOnce,它的签名如下:

z

在这里,0是起始值(假设总和为op}而z是关联二元运算符,它应用于fold,每个从左到右收集的价值。

因此301的实施方式各不相同。