在 Scala 中反转从列表元素到字符串的映射

Inverting mapping from list elements to to String in Scala

我是 Scala 的新手,我试图展平列表并反转映射。例如我有一张地图如下:

Map("abc"->List(1,2,3),"def"->List(1,5,6))

我想要的结果是:

Map(1->List("abc","def"),2->List("abc"),3->List("abc"),5->List("def"),6->List("def"))

实现此目标的最佳方法是什么?

scala> val mm = Map("abc"->List(1,2,3),"def"->List(1,5,6))
mm.toList.flatMap{ case (s, l) => l.map(ll => (ll, s))}.groupBy(_._1).map{ case (i, l) => (i, l.map(_._2))}

mm: scala.collection.immutable.Map[String,List[Int]] = Map(abc -> List(1, 2, 3), def -> List(1, 5, 6))

scala> res9: scala.collection.immutable.Map[Int,List[String]] = Map(5 -> List(def), 1 -> List(abc, def), 6 -> List(def), 2 -> List(abc), 3 -> List(abc))

scala> 

更新: 我更喜欢一个稍微不同的解决方案:

mm.toList.flatMap{ case (s, l) => 
  l.map(li => (li, s))
}.foldLeft(Map.empty[Int, List[String]]){ 
  case (m, (i, s)) => m.updated(i, s :: m.getOrElse(i, List.empty))
}

这里是你可以用简单的方式做到的

val data = Map("abc"->List(1,2,3),"def"->List(1,5,6))

val list = data.toList.flatMap(x => {
  x._2.map(y => (y, x._1))
}).groupBy(_._1).map(x => (x._1, x._2.map(_._2)))

输出:

(5,List(def))
(1,List(abc, def))
(6,List(def))
(2,List(abc))
(3,List(abc))

希望对您有所帮助!

这是另一种方法:

  Map("abc" -> List(1,2,3), "def"-> List(1,5,6)).flatMap {
    case (key, values) => values.map(elem => Map(elem -> key))
  }.flatten.foldRight(Map.empty[Int, List[String]]) { (elem, acc) =>
    val (key, value) = elem
    if (acc.contains(key)) {
      val newValues = acc(key) ++ List(value)
      (acc - key) ++ Map(key -> newValues)
    } else {
      acc ++ Map(key -> List(value))
    }
  }

所以基本上我所做的是遍历初始 Map,将其转换为元组,然后执行 foldRight 并将相同的键分组到累加器中。

这比这里发布的其他解决方案有点冗长,但我更愿意尽可能避免在我的实现中使用下划线。

另一种反转 Map 的方法:

val m = Map("abc" -> List(1, 2, 3), "def" -> List(1, 5, 6))

m.map{ case (k, v) => v.map((_, k)) }.flatten.
  groupBy(_._1).mapValues( _.map(_._2) )

// res1: scala.collection.immutable.Map[Int,scala.collection.immutable.Iterable[String]] = Map(
//   5 -> List(def), 1 -> List(abc, def), 6 -> List(def), 2 -> List(abc), 3 -> List(abc)
// )