2014-10-28 69 views
4

我的逆Scala的地图: X:[B,C] Y:并[b,d,E] Z:[d,F,G,H]如何计算多图

我想要查找此映射的逆。 b:[x,y] c:[x] d:[x,z]等等。

有没有办法做到这一点,而不使用在中间可变地图

如果它不是一个多地图 - 然后以下工作:

typeMap.flatMap { case (k, v) => v.map(vv => (vv, k))} 
+0

您能否将此标记为已完成并选择答案? – 2015-03-25 09:59:54

回答

5

编辑:固定的答案,包括什么马斯理所当然指出。我的回答比他更努力,因为我试图通过每一步,而不是使用flatMaps提供的教育用于教育目的,他更直截了当:)

我不确定你的符号。我假设你有什么是一样的东西:

val myMap = Map[T, Set[T]] (
    x -> Set(b, c), 
    y -> Set(b, d, e), 
    z -> Set(d, f, g, h) 
) 

可以实现反向查找如下:

val instances = for { 
    keyValue <- myMap.toList 
    value <- keyValue._2 
} 
yield (value, keyValue._1) 

在这一点上,您的实例变量的类型的列表:

(b, x), (c, x), (b, y) ... 

如果你现在要做的:

val groupedLookups = instances.groupBy(_._1) 

你得到:

b -> ((b, x), (b, y)), 
c -> ((c, x)), 
d -> ((d, y), (d, z)) ... 

现在我们要减少数值,以便使它们只包含每一对的第二部分。因此,我们这样做:

val reverseLookup = groupedLookup.map(_._1 -> _._2.map(_._2)) 

这意味着对于每对我们保持原有的关键,但我们的参数列表映射到的东西,只有一对的第二个值。

在那里你有你的结果。

(您也可避免被指派给中间结果,但我认为它是这样的更清晰)

+0

您构建'instances'的方式转换为'.flatMap'。 '结果集合的类型由静态类型的不可变映射引导。“(请参见[#flatMap](http://www.scala-lang.org/api/2.10.4/index.html#scala.collection .immutable.Map)),这意味着'instances'是一个'Map [A​​,B]',并且在这个过程中你将失去一些元组。 – Marth 2014-10-28 18:49:09

+1

你说得对。我修正了它,以便在更加详细的过程中反映出正确的方式,但我也提高了您的答案,因为它更直接 – 2014-10-28 20:38:01

+0

另外 - groupedLookup.map(_._ 1 - > _._ 2.map(_。_2))只能是 - groupedLookup.mapValues(_。flatMap(_._ 2)) – 2015-03-24 20:13:33

0

这里是我的简化的功能:

def reverseMultimap[T1, T2](map: Map[T1, Seq[T2]]): Map[T2, Seq[T1]] = 
    map.toSeq 
    .flatMap { case (k, vs) => vs.map((_, k)) } 
    .groupBy(_._1) 
    .mapValues(_.map(_._2)) 

以上是从@Diego Martinoia衍生“在下面的函数格式中对其进行了修正和转载:

def reverseMultimap[T1, T2](myMap: Map[T1, Seq[T2]]): Map[T2, Seq[T1]] = { 
    val instances = for { 
    keyValue <- myMap.toList 
    value <- keyValue._2 
    } yield (value, keyValue._1) 

    val groupedLookups = instances.groupBy(_._1) 
    val reverseLookup = groupedLookups.map(kv => kv._1 -> kv._2.map(_._2)) 
    reverseLookup 
}