【问题标题】:Performance consideration between /: and :\ operators in ScalaScala 中 /: 和 :\ 运算符之间的性能考虑
【发布时间】:2012-05-07 17:51:05
【问题描述】:

我觉得 insertSortRight 比 insertSortLeft 效率低,因为 insertSortRight 需要调用 List.last(即 O(n))作为 insert() 的参数之一,其中 insertSortLeft 调用 List.head(即 O(1) ) 作为 insert() 的参数之一。

这种理解正确吗?谢谢。

def insertSortRight(unsorted: List[Int]) : List[Int] = {
  (unsorted :\ List[Int]()) ((a, b) => insert(a, b))
}

def insertSortLeft(unsorted: List[Int]) : List[Int] = {
  (List[Int]() /: unsorted) ((a, b) => insert(b, a))
}  

def insert(a: Int, list: List[Int]) : List[Int] = list match {
  case List() => List(a)
  case y::ys => if (a > y) y::insert(a, ys) else a::y::ys
}

DHG 回答“总是喜欢左折叠”。但是,Scala 中的编程有一个相反的例子。

def flattenLeft[T](xss: List[List[T]]) = (List[T]() /: xss) (_ ::: ) 

def flattenRight[T](xss: List[List[T]]) = (xss :~List[T]()) ( ::: _) 

我猜是因为这种情况下 flattenRight 是通过一个函数调用实现的,而 flattenLeft 是通过 n 个函数调用实现的?

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    因此,对于List,由于需要进行头部操作,因此foldLeft 是自然选择。这样,您就可以从左到右处理列表,始终占据主导地位。如您所见,它的实现(在LinearSeqOptimized 上)只使用了一个while 循环并遍历一次。

    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
    }
    

    'foldRight' 似乎是 O(n^2),因为为了获取最后一个元素,您必须遍历 List n 的 n 元素 次,但库实际上为您优化了这一点。在幕后,foldRight 是这样实现的(也在LinearSeqOptimized 上):

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

    如你所见,这个函数是通过在尾部递归调用foldRight,将每个头部保持在堆栈中,并在到达最后一个元素后以相反的顺序将函数应用于每个头部来构造的。

    【讨论】:

    • 这些 = these.tail 的成本是多少?无论如何我觉得它是 O(n),即 foldLeft 的整体功能是 O(n^2)
    • @chen,不,List.tail 是 O(1),因为它所做的一切都让人头疼。 tail 是除了头部之外的一切;它与last 不同。 foldLeft 绝对是 O(n)。查看更多here
    • @chen List 的定义如下:List[A](head: A, tail: List[A])。所以 List.tail 只给你另一个 List,它是 O(1)。
    • 请注意,foldRight 对于Stream 操作来说是很自然的,但是,iirc,Scala 的版本并未优化。我认为 Scalaz 在Stream 上提供了优化的foldr
    猜你喜欢
    • 1970-01-01
    • 2014-05-30
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    相关资源
    最近更新 更多