Обширные коллекции Scala
У меня есть Seq[(A, B)]
, Я хотел добавить неявный метод в такие коллекции, чтобы я мог сделать .toMultiMap
чтобы вернуть Map[A, Seq[B]]
,
Это была моя первая попытка:
implicit class PairsExtensions[A, B](t: Traversable[(A, B)]) {
def toMultiMap: Map[A, Traversable[B]] = t.groupBy(_._1).mapValues(_.map(_._2))
}
Но теперь проблема в том, что я всегда Traversable
для значений. Я хочу вернуть Map[A, Set[B]]
если я сделаю Set[(A, B)].toMultiMap
,
Итак, я попробовал что-то вроде этого:
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)]
Как это сделать?
1 ответ
Решение
Я думаю, что это может быть то, что вы после.
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))