gpt4 book ai didi

scala - 反转 Scala 中的嵌套 Map

转载 作者:行者123 更新时间:2023-12-02 03:06:15 30 4
gpt4 key购买 nike

我有一个类型为 Map[A, Map[B, C]] 的 map 。

如何反转它以获得 Map[B, Map[A, C]] 类型的 Map?

最佳答案

有很多方法可以定义此操作。我将介绍几个我认为最清晰的内容。对于第一个实现,我将从辅助方法开始:

def flattenNestedMap[A, B, C](nested: Map[A, Map[B, C]]): Map[(A, B), C] =
for {
(a, innerMap) <- nested
(b, c) <- innerMap
} yield (a, b) -> c

这会将嵌套映射展平为从对到值的映射。接下来我们可以定义另一个辅助操作,它几乎可以满足我们的需要。

def groupByBs[A, B, C](flattened: Map[(A, B), C]): Map[B, Map[(A, B), C]] =
flattened.groupBy(_._1._2)

现在我们只需要从内部映射中的键中删除多余的 B 即可:

def invert[A, B, C](nested: Map[A, Map[B, C]]): Map[B, Map[A, C]] =
groupByBs(flattenNestedMap(nested)).mapValues(
_.map {
case ((a, _), c) => a -> c
}
)

(请注意,mapValues 是惰性的,这意味着每次使用它时都会重新计算结果。一般来说,这不是问题,并且有简单的解决方法,但它们是与问题不太相关。)

我们就完成了:

scala> invert(Map(1 -> Map(2 -> 3), 10 -> Map(2 -> 4)))
res0: Map[Int,Map[Int,Int]] = Map(2 -> Map(1 -> 3, 10 -> 4))

您还可以跳过辅助方法并仅在 invert 中链接操作。我发现将它们分解更清晰一些,但这是风格问题。

或者,您可以使用几次折叠:

def invert[A, B, C](nested: Map[A, Map[B, C]]): Map[B, Map[A, C]] =
nested.foldLeft(Map.empty[B, Map[A, C]]) {
case (acc, (a, innerMap)) =>
innerMap.foldLeft(acc) {
case (innerAcc, (b, c)) =>
innerAcc.updated(b, innerAcc.getOrElse(b, Map.empty).updated(a, c))
}
}

它做同样的事情:

scala> invert(Map(1 -> Map(2 -> 3), 10 -> Map(2 -> 4)))
res1: Map[Int,Map[Int,Int]] = Map(2 -> Map(1 -> 3, 10 -> 4))

foldLeft 版本具有更多直接命令式版本的形状 - 我们(在功能上)迭代外部和内部映射的键值对并构建结果。从我的角度来看,我猜它的效率也更高一些,但我不确定这一点,而且它不太重要,所以我建议选择您个人认为更清晰的那个。

关于scala - 反转 Scala 中的嵌套 Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41489003/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com