2

I have a following Scala map and I want to reverse the map, for the duplicated new key, the value will be appended to a list.

For example

val map = Map(1 -> 111, 2 -> 222, 3 -> 111)

So the result of the map is

Map(111 -> List(1,3), 222 -> 2)
ttt
  • 3,934
  • 8
  • 46
  • 85
  • 1
    @jwvh When you say "particularly nice answer" you mean "the answer I gave", right? There are certainly better answers than that one... – Tim Sep 08 '18 at 12:16

2 Answers2

3

You can use groupBy and mapValues

val map = Map(1 -> 111, 2 -> 222, 3 -> 111)
val result = map.groupBy { case (key, value) => value }.mapValues(_.keys.toList)
println(result)
// Map(222 -> List(2), 111 -> List(1, 3))

if you dont want a List when there is one element (like in your example)

val result2 = map.groupBy { case (_, value) => value }.mapValues(_.keys.toList match {
  case x :: Nil => x
  case xs       => xs
})
println(result2)
// Map(222 -> 2, 111 -> List(1, 3))
Sebastian Celestino
  • 1,388
  • 8
  • 15
0

groupBy value and map value to list of keys:

scala> val map = Map(1 -> 111, 2 -> 222, 3 -> 111)
map: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222, 3 -> 111)

scala> map.groupBy(_._2).map{case (k, v) => k -> v.keys.toList}
res0: scala.collection.immutable.Map[Int,List[Int]] = HashMap(111 -> List(1, 3), 222 -> List(2))

Or, reverse the map first with value -> key and then groupBy new key,

scala> map.map {case (k, v) => List(v -> k) }
          .groupBy { case List((a, b)) => a}
          .map { case (k, v) => k -> v.flatten.map(_._2) }
res1: scala.collection.immutable.Map[Int,scala.collection.immutable.Iterable[Int]] = HashMap(111 -> List(1, 3), 222 -> List(2))
prayagupa
  • 30,204
  • 14
  • 155
  • 192