2017-03-17 3 views
1

So。シナリオ:foldLeft on Iterable(ストリング、(Long、Long))

私は、リストのこの種類があります。

("USER1",(24,11)) 
("USER2",(10,7)) 
("USER2",(1,10)) 
("USER1",(2,3)) 
("USER3",(3,4)) 

を、私はgroupByにすべてのユーザーのすべての情報を必要として、すべてのタプルの情報を合計します。

だから私の予想される出力は次のようになります。

("USER1",(26,14)) 
("USER2",(11,17)) 
("USER3",(3,4)) 

私はこの次のコードでこれを実現:

あなたが見ることができるように userInfoIterable[String,(Long,Long)] で、私は私foldLeftを、使用
userInfo.groupBy(elem => elem._1).map(_._2).map { user => 
       { 
       val sums = user.foldLeft(("", (0L, 0L)))((acc, newElem) => 
        (acc._1, 
        (acc._2._1 + newElem._2._1, acc._2._2 + newElem._2._2))) 
       } 
      (user._1,sums) 
     } 

私は本当にfoldLeftで気にしないので、すべてのタプルの最初の要素を無視します。

私はそれがかなりひどいコードを見つけるために、基本的にこれはfoldLeft空の文字列を持っているので、これは良い解決策があるのだろうか?

+1

ない答えが、それはあることは注目に値しますCatsでは 'userInfo.foldMap(Map(_))'と書くことができます。 –

+0

@TravisBrown Catsは言語ですか?あなたのコメントを理解するにはあまりにも無知ですか? –

+0

申し訳ありませんが、[foldMap]のような抽象と便利なものを提供する[Scalaのライブラリ](https://github.com/typelevel/cats)です。 –

答えて

3

使用mapValuesとシンプルreduce

val res: Map[String, (Int, Int)] = 
    userInfo 
    .groupBy { case (user, _) => user } 
    .mapValues { it: Iterable[(String, (Int, Int))] => 
     it 
     .map { case (_, tuple) => tuple } 
     .reduce[(Int, Int)] { case ((a, b), (c, d)) => (a + c, b + d) } 
    } 
3

たぶんこれ、あなたはfoldLeftを、この場合にを減らす代わりにを使用することができます。

def sumOp(x: (Int, Int), y: (Int, Int)): (Int, Int) = (x._1 + y._1, x._2 + y._2) 

userInfo.groupBy(_._1).mapValues(user => user.map{ case (u, x) => x }.reduce(sumOp)) 
// res52: scala.collection.immutable.Map[String,(Int, Int)] = Map(USER2 -> (11,17), USER1 -> (26,14), USER3 -> (3,4)) 
関連する問題