2016-03-22 15 views
1

私はSeq[(A, B)]を持っています。そのようなコレクションに暗黙のメソッドを追加して、.toMultiMapを取得してMap[A, Seq[B]]に戻すことができます。Scalaの一般的なコレクションのコレクション

implicit class PairsExtensions[A, B](t: Traversable[(A, B)]) { 
    def toMultiMap: Map[A, Traversable[B]] = t.groupBy(_._1).mapValues(_.map(_._2)) 
    } 

しかし、今の問題は、私は常に値に対するTraversableを取り戻すです:

これが私の最初の試みでした。 Set[(A, B)].toMultiMapの場合はMap[A, Set[B]]に戻したいです。それは動作しません、

implicit class PairsExtensions2[A, B, Repr[_] <: Traversable[(A, B)]](t: TraversableLike[(A, B), Repr[(A, B)]]) { 
    def toMultiMap(implicit bf: CanBuild[B, Repr[B]]): Map[A, Repr[B]] = t.groupBy(_._1).mapValues(_.map(_._2)) 
    } 

:しかし

val m1: Map[Int, Set[String]] = Set.empty[(Int, String)] 
val m2: Map[Int, List[String]] = List.empty[(Int, String)] 

これを行う方法を教えて

だから、私はこのような何かを試してみましたか?

+0

メートル-ZL @申し訳ありませんが、明確にするために、最初の試みは、コンパイルした作品。 2番目のスニペットはコンパイルされません。私はちょうど私の試みを投稿していました。 – pathikrit

+0

ちょうど私の2セントです: 'Set'の' .toMultiMap'が 'Map [A​​、Set [B]']を与えるのが本当に理にかなっているかどうか再考したいかもしれません。前者と後者のコレクションの一意性は全く異なるでしょう。 – Owen

+0

@オウェン:わかった。問題のポイントは特に '.toMultiMap'を行うことではなく、Scalaコレクションに汎用的なutilを書く方法です。あなたが想像できるのは、 'List's私は' Map [A​​、List [B]] 'を返して、' Seq'sのために 'Map [A​​、Seq [B]]' – pathikrit

答えて

4

私はこれがあなたの後にあるかもしれないと思います。

import scala.collection.generic.CanBuildFrom 
import scala.language.higherKinds 

implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) { 
    def toMultiMap(implicit cbf: CanBuildFrom[Nothing, B, C[B]]): Map[A, C[B]] = 
    t.groupBy(_._1).mapValues(_.map(_._2).to[C]) 
} 

これは、いくつかの簡単なテストに合格:

scala> val m1: Map[Int, Set[String]] = Set.empty[(Int, String)].toMultiMap 
m1: Map[Int,Set[String]] = Map() 

scala> val m2: Map[Int, List[String]] = List.empty[(Int, String)].toMultiMap 
m2: Map[Int,List[String]] = Map() 

scala> Seq(('c',4),('x',2),('c',5)).toMultiMap 
res4: Map[Char,Seq[Int]] = Map(x -> Vector(2), c -> Vector(4, 5)) 
+0

やや接線です。地図にも同様のものがありますか?私は 'C [K、V] <:Map [K、V]'が与えられたとき、 'C [V、Set [K]]'を生成する暗黙の '反転'を追加したいと思いますか? – pathikrit

+0

具体的には、私はMap [V、Set [K]]を生成する方法を知っていますが、2つの型パラメータを取る 'C'に対して' CanBuildFrom'を動作させることができませんでした。 – pathikrit

+0

コメント欄は新しい(関連していても)トピックを開始するには悪い場所ですが、私は 'Map'インバータを持っています。 'Map [K、List [V]]を' Map [V、List [K]]に変換します。いくつかのマップ 'm'については、次のようにしてください:mapValues {_.map(_、_ 2)} ' – jwvh

関連する問題