在Scala中,如何折叠List并返回中间结果?

lin*_*lof 29 scala

我有一个月份的清单:

val days = List(31, 28, 31, ...)
Run Code Online (Sandbox Code Playgroud)

我需要返回一个累积天数的List:

val cumDays = List(31, 59, 90)
Run Code Online (Sandbox Code Playgroud)

我想过使用fold运算符:

(0 /: days)(_ + _)
Run Code Online (Sandbox Code Playgroud)

但这只会返回最终结果(365),而我需要中间结果列表.

无论如何,我可以优雅地做到这一点?

sep*_*p2k 54

Scala 2.8有这些方法scanLeft,scanRight并且正是这样做的.

对于2.7,您可以scanLeft像这样定义自己的:

def scanLeft[a,b](xs:Iterable[a])(s:b)(f : (b,a) => b) =
  xs.foldLeft(List(s))( (acc,x) => f(acc(0), x) :: acc).reverse
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

scala> scanLeft(List(1,2,3))(0)(_+_)
res1: List[Int] = List(0, 1, 3, 6)
Run Code Online (Sandbox Code Playgroud)

  • 还有`List(1,2,3).scanLeft(0)(_ + _)`. (4认同)

Lan*_*dei 18

我不确定为什么每个人似乎都坚持使用某种折叠,而你基本上想要将值映射到累积值......

val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

val cumulated = daysInMonths.map{var s = 0; d => {s += d; s}}

//--> List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
Run Code Online (Sandbox Code Playgroud)

  • 我没有看到任何问题:var没有暴露,解决方案易于理解,简短易读,计算效率高.当然,可变性的使用应该是有限的而不是过度,但不变性只是一种工具而不是教条 - 至少在任何提供可变性的语言中都是如此. (9认同)
  • 因为如果有一个使用折叠的解决方案和使用可变变量的另一个解决方案,大多数人(具有FP背景)将选择折叠. (4认同)
  • `foldLeft`的定义使用`var`s,所以在这里使用它们是很好的IMO.有时可变数据更有效,更清晰,这是一个很好的例子. (4认同)
  • 你知道看到这个解决方案特别好吗?了解多个表达式可以作为参数传递给`map`,并且范围规则是包含可变变量的.我没有在其他地方见过,但它打开了很多门...... (3认同)

小智 6

你可以简单地执行它:

daysInMonths.foldLeft((0, List[Int]()))
                     {(acu,i)=>(i+acu._1, i+acu._1 :: acu._2)}._2.reverse
Run Code Online (Sandbox Code Playgroud)