Invert a Map (String -> List) in Scala

Map inversion is a little more complicated.

val m = Map("1" -> List("a","b","c")
           ,"2" -> List("a","j","k")
           ,"3" -> List("a","c"))

m flatten {case(k, vs) => vs.map((_, k))} groupBy (_._1) mapValues {_.map(_._2)}
//res0: Map[String,Iterable[String]] = Map(j -> List(2), a -> List(1, 2, 3), b -> List(1), c -> List(1, 3), k -> List(2))

Flatten the Map into a collection of tuples. groupBy will create a new Map with the old values as the new keys. Then un-tuple the values by removing the key (previously value) elements.


An alternative that does not rely on strange implicit arguments of flatten, as requested by yishaiz:

val m = Map(
  "1" -> List("a","b","c"),
  "2" -> List("a","j","k"),
  "3" -> List("a","c"),
)

val res = (for ((digit, chars) <- m.toList; c <- chars) yield (c, digit))
  .groupBy(_._1)          // group by characters
  .mapValues(_.unzip._2)  // drop redundant digits from lists

res foreach println

gives:

(j,List(2))
(a,List(1, 2, 3))
(b,List(1))
(c,List(1, 3))
(k,List(2))