我在Programming in Scala
书中阅读了有关折叠技术的内容,并遇到了以下片段:
def reverseLeft[T](xs:List[T]) = (List[T]() /: xs) {
(y,ys) => ys :: y
}
如您所见,它是使用
foldLeft
或/:
运算符完成的。很好奇,如果我使用:\
看起来会怎样,我想到了:def reverseRight[T](xs:List[T]) = (xs :\ List[T]()) {
(y,ys) => ys ::: List(y)
}
据我了解,
:::
似乎没有::
快,并且线性开销取决于操作数列表的大小。诚然,我没有CS的背景,也没有FP的经验。所以我的问题是::::
是否有更好的方法呢? 最佳答案
由于标准库中foldRight
上的List
是严格的,并且是使用线性递归实现的,因此通常应避免使用它。 foldRight的迭代实现如下:
def foldRight[A,B](f: (A, B) => B, z: B, xs: List[A]) =
xs.reverse.foldLeft(z)((x, y) => f(y, x))
foldLeft的递归实现可能是这样的:
def foldLeft[A,B](f: (B, A) => B, z: B, xs: List[A]) =
xs.reverse.foldRight(z)((x, y) => f(y, x))
因此,您会看到,如果两者都是严格的,那么foldRight和foldLeft中的一个或另一个将通过
reverse
实现(无论如何在概念上)。由于列表的构建方式是在右侧关联::
,因此简单的迭代折叠将是foldLeft
,而foldRight
只是“先反转再将foldLeft”。直观地,您可能会认为这是foldRight的缓慢实现,因为它将列表折叠了两次。但:
foldRight
的实现比标准库中的实现更快。 关于scala - 使用foldRight反转列表的优雅方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3127793/