我是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"))
实现这一目标的最佳方法是什么?
答案 0 :(得分:3)
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))
}
答案 1 :(得分:0)
以下是您可以采用的简单方法
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))
希望这有帮助!
答案 2 :(得分:0)
这是另外一种方法:
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并将相同的键分组到累加器中。
这比这里发布的其他解决方案有点冗长,但我更愿意尽量避免在我的实现中使用下划线。
答案 3 :(得分:0)
另一种反转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)
// )