Scala:带有Traversable值的Map的隐含证据?

时间:2015-03-18 06:52:10

标签: scala collections

我试图编写一个通用的invert方法,该方法将类型为A的键的Map转换为类型为B的集合的值,并将其转换为Map使用B类型的键和使用相同原始集合类型的A集合。

我的目标是使此方法成为MyMap[A,B]类的成员,该类提供基本库方法的扩展,其中Map被隐式转换为MyMap s。我可以对通用映射执行此隐式转换,但我想进一步指定invert方法仅适用于B是集合的情况。

我对scala的集合框架缺乏理解来实现这一点 - 我已经在网上搜索了对Repr,{{1}的大杂烩的签名进行全面的介绍性解释。 },CCThat,但我真的不明白所有这些部分是如何完美地融合在一起的,足以构建我自己的方法签名。请不要给我这个案例的工作签名 - 我想了解使用泛型集合的方法的签名如何在更广泛的意义上工作,以便我能够独立地继续这样做。或者,您可以随意参考详细说明的在线资源 - 我无法找到一个全面而清晰的资源。

修改

我似乎已经使用以下代码。如果我做错了什么或者你看到可以改进的东西,请评论&用更优化的替代方案回答。

CanBuildFrom

1 个答案:

答案 0 :(得分:0)

我从你的代码开始,最后得到了这个:

implicit class MyMap[A, B, C[B] <: Traversable[B]](val _map: Map[A, C[B]]) {

  def invert(implicit cbf: CanBuildFrom[C[A], A, C[A]]): Map[B, C[A]] = {
    val inverted = scala.collection.mutable.Map.empty[B, Builder[A, C[A]]]
    for ((k, vs) <- _map; v <- vs) {
      inverted.getOrElseUpdate(v, cbf()) += k
    }

    inverted.map({ case (k, v) => (k -> v.result)}).toMap
  }
}

val map = Map("a"-> List(1,2,3), "b" -> List(1,2))

println(map.invert) //Map(2 -> List(a, b), 1 -> List(a, b), 3 -> List(a))