阅读Scala编程中的以下段落,第2版对我没有意义。
def flattenLeft[T](xss: List[List[T]]) =
(List[T]() /: xss) (_ ::: _)
def flattenRight[T](xss: List[List[T]]) =
(xss :\ List[T]()) (_ ::: _)
因为列表连接
xs ::: ys
需要时间与其成比例 第一个参数xs,在折叠方面的实现 flattenRight比折叠左实现更有效 flattenLeft。问题是flattenLeft(xss)复制了第一个 元素列表xss.head n - 1次,其中n是列表的长度 XSS
因此,如果列表连接需要的时间与其第一个参数成比例,那么意味着flattenLeft
更有效率,因为它的第一个参数是一个空列表并且{{1第一个参数是一个未知长度的列表?
答案 0 :(得分:2)
foldLeft
的第一个参数在开头只是一个空List
,即此折叠的zero
。
当您将所有List
折叠到一个List
上时,fold
会在每个连接上构建具有部分结果的中间列表,然后将其用作下一个连接的参数。这个中间结果越来越大。在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
因此,flattenRight
将花费更少的时间,因为连接的第一个参数不会随着您的进展而增长。
答案 1 :(得分:2)
通过从左侧折叠来展平列表
[ [....] [....] [....] [....] [....] ]
[....]
[...........]
[..................]
[.........................]
[................................]
,从右边开始
[ [....] [....] [....] [....] [....] ]
[....]
[...........]
[..................]
[.........................]
[................................]
从左侧折叠 n 列表时,第一个列表中的每个元素都会在(n-1)次上进行追踪;在第二个列表中(n-2)次等。这是经典的二次行为。
从右侧折叠时,每个元素都会在一次之后进行跟踪,以获得总操作的线性行为。