Elegant way to invert a map in Scala
Assuming values are unique, this works:
(Map() ++ origMap.map(_.swap))
On Scala 2.8, however, it's easier:
origMap.map(_.swap)
Being able to do that is part of the reason why Scala 2.8 has a new collection library.
You can avoid the ._1 stuff while iterating in few ways.
Here's one way. This uses a partial function that covers the one and only case that matters for the map:
Map() ++ (origMap map {case (k,v) => (v,k)})
Here's another way:
import Function.tupled
Map() ++ (origMap map tupled {(k,v) => (v,k)})
The map iteration calls a function with a two element tuple, and the anonymous function wants two parameters. Function.tupled makes the translation.
Mathematically, the mapping might not be invertible (injective), e.g., from Map[A,B]
, you can't get Map[B,A]
, but rather you get Map[B,Set[A]]
, because there might be different keys associated with same values. So, if you are interested in knowing all the keys, here's the code:
val m = Map(1 -> "a", 2 -> "b", 4 -> "b")
m.groupBy(_._2).mapValues(_.keys)
res0: Map[String,Iterable[Int]] = Map(b -> Set(2, 4), a -> Set(1))
Starting scala 2.13, this becomes even simpler and more efficient:
m.groupMap(_._2)(_._1)