我有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 :(得分: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
}