Don';我不明白foldLeft和Scala中foldRight的效率是不同的
阅读《Scala编程》第二版中的以下段落,这对我来说毫无意义Don';我不明白foldLeft和Scala中foldRight的效率是不同的,scala,fold,Scala,Fold,阅读《Scala编程》第二版中的以下段落,这对我来说毫无意义 def flattenLeft[T](xss: List[List[T]]) = (List[T]() /: xss) (_ ::: _) def flattenRight[T](xss: List[List[T]]) = (xss :\ List[T]()) (_ ::: _) 因为列表串联,xs:::ys,需要的时间与它的 第一个参数xs,在折叠权方面的实现 在中,FlatterRight比fold left实现更高效
def flattenLeft[T](xss: List[List[T]]) =
(List[T]() /: xss) (_ ::: _)
def flattenRight[T](xss: List[List[T]]) =
(xss :\ List[T]()) (_ ::: _)
因为列表串联,xs:::ys
,需要的时间与它的
第一个参数xs,在折叠权方面的实现
在中,FlatterRight比fold left实现更高效
向左转。问题是Flattleft(xss)复制了第一个
元素列表xss.head n− 1次,其中n是列表的长度
xss
因此,如果列表串联所需的时间与其第一个参数成比例,这是否意味着
flattleft
更有效,因为它的第一个参数是一个空列表,flattright
的第一个参数是一个长度未知的列表?foldLeft的第一个参数在开始时只是一个空的列表,也就是说,这个折叠的zero
当您将所有的列表
折叠到一个列表
上时,折叠
会构建中间列表,其中包含每个串联的部分结果,然后用作下一个串联的参数。这个中间结果越来越大。在foldLeft
上,这将是第一个参数:
def flattenLeft[T](xss: List[List[T]]) =
(List[T]() /: xss) ((acc, xs) => acc ::: xs )
//^ this one
相反,对于foldRight
来说,从右边构建结果,这意味着中间结果(增长的结果)是右边的结果,这将是连接操作的第二个参数
def flattenRight[T](xss: List[List[T]]) =
(xss :\ List[T]()) ((xs, acc) => xs ::: acc)
//^ this one gets bigger now
因此,一个flattright
将花费更少的时间,因为要连接的第一个参数不会随着您的进度而增长。通过从左侧折叠来展平列表的过程如下所示:
[ [....] [....] [....] [....] [....] ]
[....]
[...........]
[..................]
[.........................]
[................................]
从右边开始
[ [....] [....] [....] [....] [....] ]
[....]
[...........]
[..................]
[.........................]
[................................]
当从左侧折叠n个列表时,第一个列表中的每个元素被跟踪(n-1)次;在第二个列表中(n-2)次等。这是典型的二次行为
从右侧折叠时,每个元素都会精确跟踪一次,以实现整个操作的线性行为