简体   繁体   English

Scala:具有可遍历值的Map的隐式证据?

[英]Scala: Implicit evidence of Map with Traversable values?

I'm trying to write a generic invert method that takes a Map from keys of type A to values that are collections of type B and converts it to a Map with keys of type B and collections of A using the same original collection type. 我试图写一个通用的invert方法,该方法从类型的密钥的地图A到那些类型的收藏价值B并将其转换为与类型的密钥的地图B和集合A使用相同的原始集合类型。

My goal is to make this method a member of a MyMap[A,B] class that offers extensions of the basic library methods, where Map s are implicitly converted to MyMap s. 我的目标是使该方法成为MyMap[A,B]类的成员,该类提供基本库方法的扩展,其中Map隐式转换为MyMap I am able to do this implicit conversion for a generic map, but I want to further specify that the invert method should only work in the case where B is a collection. 我可以对泛型映射执行此隐式转换,但是我想进一步指定invert方法仅在B是集合的情况下才有效。

I lack the understanding of scala's collections framework to accomplish this - I've scoured the net for thorough introductory explanations of the signatures that look like a hodgepodge of Repr , CC , That , and CanBuildFrom , but I don't really understand how all these pieces fit together well enough to construct the method signature on my own. 我缺乏对scala的collections框架的了解以完成此任务-我在网上搜寻了有关签名的完整介绍性解释,这些签名看起来像是ReprCCThatCanBuildFrom ,但我真的不太了解所有这些各个部分很好地结合在一起,可以自己构造方法签名。 Please don't just give me the working signature for this case - I want to understand how the signatures of methods that use generic collections work in a broader sense so I'm able to do this independently going forward. 请不要只给我这种情况下的工作签名-我想了解使用泛型集合的方法的签名在更广泛的意义上是如何工作的,因此我能够独立地进行此工作。 Alternatively, feel free to reference an online resource that elaborates on this - I was unable to find one that was comprehensive and clear. 另外,请随时参考详细介绍此内容的在线资源-我找不到一个全面而清晰的资源。

EDIT 编辑

I seem to have gotten it to work with the following code. 我似乎已经将其与以下代码一起使用。 If I did something wrong or you see something that can be improved, please comment & answer with a more optimal alternative. 如果我做错了什么,或者您发现可以改进的地方,请用更理想的替代方法进行评论和回答。

class MyMap[A, B](val _map: Map[A, B]) {
  def invert[E, CC[E]](
    implicit ev1: B =:= CC[E],
    ev2: CC[E] <:< TraversableOnce[E],
    cbf: CanBuildFrom[CC[A], A, CC[A]]
  ): Map[E, CC[A]] = {
    val inverted = scala.collection.mutable.Map.empty[E, Builder[A, CC[A]]]
    for {
      (key, values) <- _map
      value <- values.asInstanceOf[CC[E]]
    } {
      if (!inverted.contains(value)) {
        inverted += (value -> cbf())
      }
      inverted.get(value).foreach(_ += key)
    }
    return inverted.map({ case (k,v) => (k -> v.result) }).toMap
  }
}

I started from your code and ended up with this: 我从您的代码开始,到此为止:

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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM