繁体   English   中英

左折右折

[英]Fold left and fold right

我正在尝试学习如何使用向左折叠和向右折叠。 这是我第一次学习函数式编程。 我无法理解何时使用向左折叠以及何时使用向右折叠。 在我看来,很多时候这两个功能是可以互换的。 例如(在 Scala 中)这两个函数:

val nums = List(1, 2, 3, 4, 5)

val sum1 = nums.foldLeft(0) { (total, n) =>
  total + n
}
val sum2 = nums.foldRight(0) {(total, n) =>
  total + n
}

两者都产生相同的结果。 为什么以及什么时候我会选择一个或另一个?

foldleft和foldright在函数嵌套方式上有所不同。

foldleft: (((...) + a) + a) + a
foldright: a + (a + (a + (...)))

由于您正在使用的功能是加法运算,因此两者都给出相同的结果。 尝试使用减法。

而且,使用fold(left / right)的动机不是结果-在大多数情况下,两者都产生相同的结果。 这取决于您要聚合的功能。

由于您使用的运算符是关联的和可交换的运算符意味着a + b = b + a这就是为什么leftFoldrightFold工作等效但它通常不等效,因为您可以通过下面的示例可视化,其中 operator(+)不是关联和可交换的操作即在字符串连接的情况下 '+' 运算符不是关联和交换的意思是'a' + 'b' != 'b' + 'a'

val listString = List("a", "b", "c") // : List[String] = List(a,b,c)
val leftFoldValue = listString.foldLeft("z")((el, acc) => el + acc) // : String = zabc
val rightFoldValue = listString.foldRight("z")((el, acc) => el + acc) // : abcz 

或以速记方式

val leftFoldValue = listString.foldLeft("z")(_ + _) // : String = zabc
val rightFoldValue = listString.foldRight("z")(_ + _) // : String = abcz

解释:

leftFold的工作方式为( ( ('z' + 'a') + 'b') + 'c') = ( ('za' + 'b') + 'c') = ('zab' + 'c') = 'zabc'

rightFold as ('a' + ('b' + ('c' + 'z'))) = ('a' + ('b' + 'cz')) = ('a' + 'bcz') = 'abcz'

因此,简而言之,对于关联和交换的运算符,foldLeft 和 foldRight 是等价的(尽管效率可能存在差异)。 但有时,两个运算符中只有一个是合适的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM