Wednesday, March 10, 2010

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

  1. scala> val nodupes = Map(1 -> "a", 2-> "b", 3 -> "c")
  2. nodupes: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b), (3,c))
  3. // Scala 2.8+
  4. scala> nodupes map {_.swap}                          
  5. res4: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3))
  6. // Scala 2.7
  7. scala> Map() ++ (nodupes map {case (k,v) => (v,k)})  
  8. res5: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3))
  9. // watch out if the values have duplicates you will loose information:
  10. scala> val dupes = Map(1 -> "a", 2-> "b", 3 -> "b")  
  11. dupes: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b), (3,b))
  12. scala> dupes map {_.swap}                          
  13. res6: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,3))
  14. // a way to not loose any data
  15. scala> dupes groupBy {_._2} map {case (key,value) => (key, value.unzip._1)}     
  16. res12: scala.collection.Map[java.lang.String,scala.collection.immutable.Iterable[Int]] = Map((a,List(1)), (b,List(2, 3)))
  17. // I wanted to do the following for performance:
  18. scala> dupes.view groupBy {_._2} map {case (key,value) => (key, value.unzip._1)}
  19. java.lang.UnsupportedOperationException: IterableView((1,a), (2,b), (3,b)).newBuilder
  20. at scala.collection.TraversableViewLike$class.newBuilder(TraversableViewLike.scala:40)
  21. at scala.collection.IterableLike$$anon$1.newBuilder(IterableLike.scala:363)
  22. at scala.collection.TraversableLike$$anonfun$groupBy$1.apply(TraversableLike.scala:370)
  23. // but as you can see a view cannot yet be grouped.  Perhaps in the future.

3 comments:

  1. Hi,

    Yes, views have that issue. See ticket #3117 for another example:

    https://lampsvn.epfl.ch/trac/scala/ticket/3117

    Best,
    Ismael

    ReplyDelete
  2. pretty cool your hack to inverse a Map with non-unique values! thanks!

    ReplyDelete
  3. Nice stuff! Thanks for an example with 'not loosing any data'

    ReplyDelete