首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >foldRight效率?

foldRight效率?
EN

Stack Overflow用户
提问于 2012-06-13 04:53:44
回答 2查看 1.6K关注 0票数 9

我听说foldLeft在大多数操作中效率更高,但Scala School (来自推特)给出了以下示例。有人能分析一下它的效率吗?我们应该用foldLeft实现同样的操作吗?

代码语言:javascript
复制
val numbers = List(1,2,3,4,5,...10)
def ourMap(numbers: List[Int], fn: Int => Int): List[Int] = {
    numbers.foldRight(List[Int]()) { (x: Int, xs: List[Int]) =>
    fn(x) :: xs
  }
}

scala> ourMap(numbers, timesTwo(_))
res0: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-13 06:47:15

正如您从文档中看到的,List的foldRight和foldLeft方法都是在LinearSeqOptimized中定义的。

代码语言:javascript
复制
override /*TraversableLike*/
def foldLeft[B](z: B)(f: (B, A) => B): B = {
  var acc = z
  var these = this
  while (!these.isEmpty) {
    acc = f(acc, these.head)
    these = these.tail
  }
  acc
}

override /*IterableLike*/
def foldRight[B](z: B)(f: (A, B) => B): B =
  if (this.isEmpty) z
  else f(head, tail.foldRight(z)(f))

因此,foldLeft使用while循环,而foldRight使用简单的递归方法。特别是,它不是尾递归的。因此,foldRight会产生创建新堆栈帧的开销,并且如果您在一个很长的列表上尝试它(尝试,例如((1 to 10000).toList :\ 0)(_+_) ),则会导致堆栈溢出。轰隆隆!但它在没有toList的情况下工作得很好,因为RangefoldRight是通过反转左侧折叠来工作的)。

那么为什么不总是使用foldLeft呢?对于链表,右折叠可以说是一种更自然的功能,因为链表需要以相反的顺序构建。您可以对上面的方法使用foldLeft,但您需要在最后对输出进行reverse。(不要试图附加到左文件夹中的列表,因为复杂度是O(n平方)。)

至于在实践中哪个更快,foldRightfoldLeft + reverse,我运行了一个简单的测试,对于列表,foldRight的速度快了10%到40%。这一定是为什么List的foldRight是以这种方式实现的。

票数 15
EN

Stack Overflow用户

发布于 2012-06-13 05:18:04

foldRight反转列表并应用foldLeft。

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

https://stackoverflow.com/questions/11004715

复制
相关文章

相似问题

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