如何计算多图的逆

时间:2014-10-28 17:05:18

标签: scala map

我有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))}

2 个答案:

答案 0 :(得分:5)

编辑:修正答案,包括Marth正确指出的内容。当我尝试完成每一步并且不使用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))

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

你有结果。

(您也可以避免分配中间结果,但我认为这样更清晰)

答案 1 :(得分: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
}