2013-02-08 66 views
1

Haskell有一个函数accumArray函数,它通过一个键对2元组进行分组,然后用相同的键减少值。斯卡拉没有一个,似乎有一个在斯卡拉,但依赖于许多其他斯卡拉特征。 有没有更好的方式在scala中编写accumArray? 详细的这一功能在Haskell这里:http://zvon.org/other/haskell/Outputarray/accumArray_f.htmlhaskell accumArra在scala中相当于?

下面是我的实现。谢谢。

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

应该在http://codereview.stackexchange.com – luqui 2013-02-08 22:00:29

回答

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()) 
} 
0

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

我还没有学会足够ScalaZ(函数式编程)的给你一个工作的例子,但似乎你有经验,Haskell和可能有足够的知识,要做到这一点ScalaZ。