Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: map a Map to list of tuples

I tried to use Map.map to convert a map into a List of Tuples. However this fails. I did the following experiments:

val m = Map(("a" -> 1), ("b" -> 2))
         //> m  :     scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
val r1 = m.map{ case (k,v) => v}                //> r1  : scala.collection.immutable.Iterable[Int] = List(1, 2)
def toTuple[A,B](a:A,b:B) = (a,b)               //> toTuple: [A, B](a: A, b: B)(A, B)
//val r2: List[Tuple2[_,_]] = m.map(e => (e._1,e._2))
val r3 = m.map(e => toTuple(e._1,e._2))         //> r3  : scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
val r4 = m.toSeq                                //> r4  : Seq[(String, Int)] = ArrayBuffer((a,1), (b,2))

Notice how a List is generated for single elements (r1) but a Map is produced for tuples (r3). Not even forcing the type worked (r2). Only an explicit call to Seq did it (r4) So my question is, why/how does Map.map "automagically" create a new Map and not a list for example? In fact how is the return type determined (Seq, List, etc.)

like image 686
user2051561 Avatar asked Feb 27 '15 16:02

user2051561


People also ask

What does map () do in Scala?

map() method is a member of TraversableLike trait, it is used to run a predicate method on each elements of a collection. It returns a new collection.

What is a list map in Scala?

Scala map is a collection of key/value pairs. Any value can be retrieved based on its key. Keys are unique in the Map, but values need not be unique. ListMap implements immutable map and uses list to implement the same. It is used with small number of elements.

Are maps tuples?

a pair is a tuple that only holds two values. a map is a structure that (conceptually) holds multiple pairs and allows efficient lookups by the first element in the pair (the key). They also do not allow the first elements of any pairs to be the same.

How do you access map elements in Scala?

Scala Map get() method with exampleThe get() method is utilized to give the value associated with the keys of the map. The values are returned here as an Option i.e, either in form of Some or None. Return Type: It returns the keys corresponding to the values given in the method as argument.


1 Answers

A Map is a collection of tuples already.

scala> "b" -> 2
res0: (String, Int) = (b,2) // Implicitly converted to a Tuple

When you're mapping a Map, you're mapping the (key, value) pairs that it contains. This can't work, because you're stripping away the keys, and retaining only the values. So what you have is no longer a Map, but a step or two up the collection hierarchy, an Iterable:

val r1 = m.map{ case (k,v) => v} 

Forcing the type cannot work, because a Map[A, B] is not a List[(A, B)]. This is the equivalent of m.map(identity). Notice how you're even accessing e with tuple accessors:

val r2: List[Tuple2[_,_]] = m.map(e => (e._1,e._2))

val r3 = m.map(e => toTuple(e._1,e._2))

Here, Seq is more generalized than List:

val r4 = m.toSeq

The simple solution as stated by @EndeNeu is to just use toList. When you map a collection, it should return the original collection type if it can. So mapping a Map should return another Map, unless the underlying structure has made it no longer a Map (like removing keys entirely) in r1.

like image 122
Michael Zajac Avatar answered Oct 22 '22 14:10

Michael Zajac