繁体   English   中英

反转Scala中的嵌套地图

[英]Inverse a nested Map in Scala

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

如何使它具有Map[B, Map[A, C]]类型的Map[B, Map[A, C]]呢?

您可以通过多种方式定义此操作。 我将介绍一些我认为最清楚的方法。 对于第一个实现,我将从助手方法开始:

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版本具有直接命令式版本的更多形状-我们在功能上迭代外部和内部映射的键值对并构建结果。 我想我的头顶上还有一点点效率,但是我不确定,这不太重要,所以我建议选择一个您自己觉得更清晰的型号。

您可以简单地使用给定Map集合上的map操作来做到这一点:

scala> Map("A" -> Map("B" -> "C"), "X" -> Map("Y" -> "Z"))
res1: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]] = Map(A -> Map(B -> C), X -> Map(Y -> Z))

scala> res1.map{ case (key, valueMap) => valueMap.map{ case (vmKey, vmValue) => (vmKey -> Map(key -> vmValue)) } }
res2: scala.collection.immutable.Iterable[scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]]] = List(Map(B -> Map(A -> C)), Map(Y -> Map(X -> Z)))  

暂无
暂无

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

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