zig*_*tar 16 functional-programming scala
我遇到过在整个地图操作中多次维护状态的问题.想象一下以下任务:
给定List [Int],将每个元素映射到所有前面元素和它自身的总和.
因此1,2,3变为1,1 + 2,1 + 2 + 3.
我提出的一个解决方案是:
scala> val a = 1 to 5
a: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5)
scala> a.foldLeft(List(0)){ case (l,i) => (l.head + i) :: l }.reverse
res3: List[Int] = List(0, 1, 3, 6, 10, 15)
Run Code Online (Sandbox Code Playgroud)
但不知何故,我觉得必须有一个更简单的解决方案.
Dar*_*rio 31
您正在尝试计算部分和的序列.
计算此类累积的一般操作不是,fold但是scan,虽然scan可以通过fold您显示的方式表达(并且fold实际上是生成的列表的最后一个元素scan).
至于斯卡拉,我会给出这个例子
scala> scanLeft(List(1,2,3))(0)(_ + _)
res1: List[Int] = List(0, 1, 3, 6)
Run Code Online (Sandbox Code Playgroud)
@Dario给出了答案,但只是添加scala库提供scanLeft:
scala> List(1,2,3).scanLeft(0)(_ + _)
res26: List[Int] = List(0, 1, 3, 6)
Run Code Online (Sandbox Code Playgroud)
的scan回答是最好的,但值得注意的是,一个可以使褶皱看起来更漂亮和/或比你的问题更短.首先,您不需要使用模式匹配:
a.foldLeft(List(0)){ (l,i) => (l.head + i) :: l }.reverse
Run Code Online (Sandbox Code Playgroud)
其次,请注意foldLeft有一个缩写:
(List(0) /: a){ (l,i) => (l.head + i) :: l }.reverse
Run Code Online (Sandbox Code Playgroud)
第三,请注意,如果需要,您可以使用可以有效附加的集合,这样您就不需要反转:
(Vector(0) /: a){ (v,i) => v :+ (v.last + i) }
Run Code Online (Sandbox Code Playgroud)
因此,虽然这不像以下那样紧凑scanLeft:
a.scanLeft(0)(_ + _)
Run Code Online (Sandbox Code Playgroud)
它仍然不是太糟糕.