【问题标题】:Scala: Producing the intermediate results of a foldScala:产生折叠的中间结果
【发布时间】:2012-07-26 16:55:34
【问题描述】:

我多次遇到过在整个地图操作中维护状态的问题。想象一下以下任务:

给定一个 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)

但不知何故,我觉得必须有一个更简单的解决方案。

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    您正在尝试计算部分和的序列。

    计算此类累加的一般操作不是fold,而是scan,尽管scan 可以通过fold 以您展示的方式表达(而fold 实际上是由scan)。

    至于 Scala,我会给这个example

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

    【讨论】:

    • 确实,有一个 scanLeft 函数,它正是我需要的。如果您或其他人将添加其用法的有效 scala 示例,我将接受此答案。
    • 用我找到的一些例子编辑了答案。使用更好的语法,a scanLeft(0) { (a, b) => a + b } 可能仍然有效
    • scala> List(1,2,3).scanLeft(0)(_+_)
    • 有趣的是,在你的链接之后,它说“以下示例来自 SO”。
    【解决方案2】:

    @Dario 给出了答案,但只是补充说 scala 库提供了 scanLeft:

    scala> List(1,2,3).scanLeft(0)(_ + _)
    res26: List[Int] = List(0, 1, 3, 6)
    

    【讨论】:

      【解决方案3】:

      scan 的答案是最好的答案,但值得注意的是,可以使折叠看起来更好和/或比您的问题更短。首先,您不需要使用模式匹配:

      a.foldLeft(List(0)){ (l,i) => (l.head + i) :: l }.reverse
      

      第二,注意foldLeft有个缩写:

      (List(0) /: a){ (l,i) => (l.head + i) :: l }.reverse
      

      第三,请注意,如果您愿意,可以使用可以高效追加的集合,这样您就不需要反转:

      (Vector(0) /: a){ (v,i) => v :+ (v.last + i) }
      

      因此,虽然它不像 scanLeft 那样紧凑:

      a.scanLeft(0)(_ + _)
      

      还不错。

      【讨论】:

      • 当您的二进制操作的类型不是 (B, B) => B,而是 (C, B) => C 时,这很有用
      【解决方案4】:

      我和其他人一样喜欢折叠,但较少 FP 的答案非常简洁易读:

       a.map{var v=0; x=>{v+=x; v}}
      

      【讨论】:

      • 吹毛求疵,但不知map调用其参数函数时是否保证顺序。
      • @HRJ - 保证连续收藏。不能保证并行收集,但是您会遇到更严重的问题(未在v 上同步)。
      猜你喜欢
      • 2011-03-14
      • 2017-10-11
      • 2012-03-31
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-07
      • 1970-01-01
      相关资源
      最近更新 更多