Elegant way to invert a map in Scala

scala map
scala reverse list
scala create map
scala add to map if not exists
scala flip tuple
scala map of map
scala immutable map
scala mutable map

Learning Scala currently and needed to invert a Map to do some inverted value->key lookups. I was looking for a simple way to do this, but came up with only:

(Map() ++ origMap.map(kvp=>(kvp._2->kvp._1)))

Anybody have a more elegant approach?

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.

Elegant way to invert a map in Scala - scala - html, Elegant way to invert a map in Scala - scala. I was looking for a simple way to do this, but came up with only: (Map() ++ origMap.map(kvp=>(kvp._2->kvp. By default, Scala uses the immutable Map. If you want to use the mutable Map, you'll have to import scala.collection.mutable.Map class explicitly. If you want to use both mutable and immutable Maps in the same, then you can continue to refer to the immutable Map as Map but you can refer to the mutable set as mutable.Map.

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:

scala> val m = Map(1 -> "a", 2 -> "b", 4 -> "b")
scala> m.groupBy(_._2).mapValues(_.keys)
res0: Map[String,Iterable[Int]] = Map(b -> Set(2, 4), a -> Set(1))

How to reverse a map, How to reverse a map. scala> val nodupes = Map(1 -> "a", 2-> "b", 3 -> "c") nodupes: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b), (3,c)) // Scala 2.8+ scala> nodupes map {_.swap} res4: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3)) // Scala 2.7. How to reverse a map Suppose you wish to take a map and swap the keys with values. The stackoverflow question Elegant way to revers a map in scala offers some good suggestions

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.

How to reverse keys and values in a Scala Map, This is an excerpt from the Scala Cookbook (partially modified for the internet). This is one the smallest recipes, Recipe 11.20, “How to Reverse  A Map is an Iterable consisting of pairs of keys and values (also named mappings or associations).Scala’s Predef object offers an implicit conversion that lets you write key -> value as an alternate syntax for the pair (key, value).

I came here looking for a way to invert a Map of type Map[A, Seq[B]] to Map[B, Seq[A]], where each B in the new map is associated with every A in the old map for which the B was contained in A's associated sequence.

E.g., Map(1 -> Seq("a", "b"), 2-> Seq("b", "c")) would invert to Map("a" -> Seq(1), "b" -> Seq(1, 2), "c" -> Seq(2))

Here's my solution :

val newMap = oldMap.foldLeft(Map[B, Seq[A]]().withDefaultValue(Seq())) {
  case (m, (a, bs)) => bs.foldLeft(m)((map, b) => map.updated(b, m(b) :+ a))
}

where oldMap is of type Map[A, Seq[B]] and newMap is of type Map[B, Seq[A]]

The nested foldLefts make me cringe a little bit, but this is the most straightforward way I could find to accomplish this type of inversion. Anyone have a cleaner solution?

How to Reverse keys and values in Scala Map, In Scala, Map is same as dictionary which holds key:value pairs. In this article, we will learn how to reverse the keys and values in given Map in Scala. You can reverse the keys and values of a map with a Scala for-comprehension, being sure to assign the result to a new variable: val reverseMap = for ((k,v) <- map) yield (v, k) But be aware that values don’t have to be unique and keys must be, so you might lose some content.

OK, so this is a very old question with many good answers, but I've built the ultimate, be-all-and-end-all, Swiss-Army-knife, Map inverter and this is the place to post it.

It's actually two inverters. One for individual value elements...

//from Map[K,V] to Map[V,Set[K]], traverse the input only once
implicit class MapInverterA[K,V](m :Map[K,V]) {
  def invert :Map[V,Set[K]] =
    m.foldLeft(Map.empty[V, Set[K]]) {
      case (acc,(k, v)) => acc + (v -> (acc.getOrElse(v,Set()) + k))
    }
}

...and another, quite similar, for value collections.

import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
import scala.language.higherKinds

//from Map[K,C[V]] to Map[V,C[K]], traverse the input only once
implicit class MapInverterB[K,V,C[_]](m :Map[K,C[V]]
                                     )(implicit ev :C[V] => TraversableOnce[V]) {
  def invert(implicit bf :CanBuildFrom[Nothing,K,C[K]]) :Map[V,C[K]] =
    m.foldLeft(Map.empty[V, Builder[K,C[K]]]) {
      case (acc, (k, vs)) =>
        vs.foldLeft(acc) {
          case (a, v) => a + (v -> (a.getOrElse(v,bf()) += k))
        }
    }.mapValues(_.result())
}

usage:

Map(2 -> Array('g','h'), 5 -> Array('g','y')).invert
//res0: Map(g -> Array(2, 5), h -> Array(2), y -> Array(5))

Map('q' -> 1.1F, 'b' -> 2.1F, 'c' -> 1.1F, 'g' -> 3F).invert
//res1: Map(1.1 -> Set(q, c), 2.1 -> Set(b), 3.0 -> Set(g))

Map(9 -> "this", 8 -> "that", 3 -> "thus", 2 -> "thus").invert
//res2: Map(this -> Set(9), that -> Set(8), thus -> Set(3, 2))

Map(1L -> Iterator(3,2), 5L -> Iterator(7,8,3)).invert
//res3: Map(3 -> Iterator(1, 5), 2 -> Iterator(1), 7 -> Iterator(5), 8 -> Iterator(5))

Map.empty[Unit,Boolean].invert
//res4: Map[Boolean,Set[Unit]] = Map()

I would prefer to have both methods in the same implicit class but the more time I spent looking into it the more problematic it appeared.

Bit Twiddling Hacks, Compute parity of a word the naive way; Compute parity by lookup table Reverse bits the obvious way; Reverse bits in word by lookup table; Reverse the bits put the result in r static const int Mod37BitPosition[] = // map a bit value mod 37  This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 11.23, “How to Sort an Existing Map by Key or Value” Problem. You have an unsorted Scala Map and want to sort the elements in the map by the key or value.

A Quick Guide to Concurrency in Scala, So by default when you build a List , Map , or Case Class in Scala it is Think of a Scala Future as a simple way of saying do this thing in the background. via invert via doubler to sink // run them runnable.run() /* OUTPUT: -2 -4 -6 */ I found it to be an elegant system that made testing my background  Scala vs. Groovy vs. Clojure ; Is the Scala 2.8 collections library a case of “the longest suicide note in history”? Difference between object and class in Scala ; Elegant way to invert a map in Scala ; Large-scale design in Haskell?

Java developer's Scala cheatsheet by mbonaci, 153 - The Scala compiler will internally “mangle” operator identifiers to turn 190 - filter method takes a function that maps each element to true or false, same problem can be solved with more elegant solution, without any dead reverse sort (underscore stands for missing arguments list, in this case,  Any elegant way to do this other than iterating the keys and adding the swapped key/value pair to a new Map?. I have a Map<String,String> (actually a TreeMap) that I need to reverse the keys and values because I need the keys corresponding to the values in alphabetical order.

Introduction to Programming in Apache Scala Tutorial, general programming patterns in an elegant, precise, and type-safe way. Additionally, you can use the unary operator for inverting a Boolean value. Map​. maps in scala. The example given above shows how to declare immutable maps. Save the above program in Demo.scala. The following commands are used to compile and execute this program. Command \>scalac Demo.scala \>scala Demo Output Concatenated String: (1,hello,scala.Console$@281acd47) Swap the Elements. You can use Tuple.swap method to swap the elements of a Tuple2. Try the following example program to swap the

Comments
  • Careful! You can loose values with this solution. For example Map(1 -> "A", 2 -> "B", 3 -> "B").map(_.swap) results in Map(A -> 1, B -> 3)
  • @dev-null I'm sorry, but your example does not fall under the required assumption.
  • I agree. Sorry, I've overlooked that.
  • .map(_._1) would be more legibile as just .keys
  • Now thanks to you, even a few characters shorter. The difference now is that you get Sets instead of Lists as before.
  • Be careful when using .mapValues because it returns a view. Occasionally, this is what you want, but if you aren't careful it can consume lots of memory and CPU. To force it into a map, you can do m.groupBy(_._2).mapVaues(_.keys).map(identity), or you could replace the call to .mapValues(_.keys) with .map { case (k, v) => k -> v.keys }.
  • very nice solution! @Rok, his solution is somehow different than yours a bit I think because he transforms: Map[A, Seq[B]] to Map[B, Seq[A]] where your solution trasnforms Map[A, Seq[B]] to Map[Seq[B], Seq[A]].
  • In that case, without two nested folds and possible more performant: a.toSeq.flatMap { case (a, b) => b.map(_ -> a) }.groupBy(_._2).mapValues(_.map(_._1))
  • This is perfect! Thank you very much for your contribution.
  • Too bad it won't transform Map[K, C[V]] into Map[V, C[K]].