在scala中haskell accumArray等效?

时间:2013-02-08 21:52:33

标签: scala haskell scala-collections

Haskell有一个函数accumArray函数,它通过键对2元组进行分组,然后使用相同的键减少值。 Scala没有,scalaz似乎有一个,但取决于许多其他scalaz功能。 有没有更好的方法在scala中编写accumArray? 详情来自haskell中的这个函数:http://zvon.org/other/haskell/Outputarray/accumArray_f.html

以下是我的实施。感谢。

  private def accumArray[A <% Ordered[A], B, C](f: (B, C) => B,
                                                base: B,
                                                bounds: (A, A),
                                                ll: List[(A, C)]): Vector[(A, B)] = {
    ll.filter(i => i._1 >= bounds._1 && i._1 <= bounds._2).
      groupBy(_._1).
      map(e =>
        e._1 -> e._2.map(_._2).foldLeft(base)(f)
      ).
      toVector
  }

2 个答案:

答案 0 :(得分:1)

这是我的解决方案,而不是那么短暂

def accumArray[A <% Ordered[A], B, C](f: (B, C) => B,
                                      base: B,
                                      bounds: (A, A),
                                      xs: Seq[(A, C)]): Vector[(A, B)] = {
  @scala.annotation.tailrec
  def accum(ys: Seq[(A, C)], zs: Vector[(A, B)]): Vector[(A, B)] =
    (ys, zs) match {
      case(Seq(), _)           => zs
      case(((a,c)) +: rs, Vector())  => accum(rs, Vector((a, f(base,c))))
      case(((a1,c)) +: rs, vs :+ ((a2,b))) =>
        if(a1 == a2) accum(rs, vs :+ (a2, f(b,c)))
        else accum(rs, zs :+ (a1, f(base,c)))
    }

  val (min, max) = bounds
  val ys = xs.filter{case(x, _) => x >= min && x <= max}.sortBy(_._1)
  accum(ys, Vector())
}

答案 1 :(得分:0)

元组列表可以看作是键值对的列表。这让我想起了Map类型。使用ScalaZ显然可以累积Map:Using scala Maps to accumulate values

我还没有学到足够的ScalaZ(函数式编程)给你一个工作的例子,但是看起来你有使用Haskell的经验,并且可能有足够的知识来使用ScalaZ。