Scala: map a Map to list of tuples
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
.
user2051561
Updated on July 21, 2022Comments
-
user2051561 almost 2 years
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.)
-
user2051561 about 9 yearsThanks m-z. My question is really: in the case of
r1
, how doesMap
know it should convert to aList
? It could have been something else? Why not an array? I am assuming their is some implicit conversion going on here. Hence my testing by forcing types. In regards to the Tuples, makes sense. That's the Map convention. -
Michael Zajac about 9 years@user2051561 It doesn't convert it to a
List
inr1
--it returnsIterable
because that's the next closest trait up the hierarchy that matches the type of collection you have.Map
extendsIterable
.