Reputation: 13
I have a "dirtyMap" which is immutable.Map[String, collection.mutable.Set[String]]. I want to convert dirtyMap to immutable Map[String, Set[String]]. Could you please let me know how to do this. I tried couple of ways that didn't produce positive result
Method 1: Using map function
dirtyMap.toSeq.map(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
I'm getting syntax error
Method 2: Using foreach
dirtyMap.toSeq.foreach(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
cannot apply toMap to output of foreach
Disclaimer: I am a Scala noob if you couldn't tell.
UPDATE: Method 1 works when I remove parenthesis from toMap() function. However, following is an elegant solution
dirtyMap.mapValues(v => v.toSet)
Thank you Gabriele for providing answer with a great explanation. Thanks Duelist and Debojit for your answer as well
Upvotes: 0
Views: 842
Reputation: 108101
You can simply do:
dirtyMap.mapValues(_.toSet)
mapValues
will apply the function to only the values of the Map
, and .toSet
converts a mutable Set
to an immutable one.
(I'm assuming dirtyMap
is a collection.immutable.Map
. In case it's a mutable one, just add toMap
in the end)
If you're not familiar with the underscore syntax for lambdas, it's a shorthand for:
dirtyMap.mapValues(v => v.toSet)
Now, your first example doesn't compile because of the ()
. toMap
takes no explicit arguments, but it takes an implicit argument. If you want the implicit argument to be inferred automatically, just remove the ()
.
The second example doesn't work because foreach
returns Unit
. This means that foreach
executes side effects, but it doesn't return a value. If you want to chain transformations on a value, never use foreach
, use map
instead.
Upvotes: 1
Reputation: 1572
You can use flatMap
for it:
dirtyMap.flatMap(entry => Map[String, Set[String]](entry._1 -> entry._2.toSet)).toMap
Firstly you map
each entry to immutable.Map(entry)
with updated entry, where value is immutable.Set
now. Your map looks like this: mutable.Map.
And then flatten
is called, so you get mutable.Map
with each entry with immutable.Set
. And then toMap converts this map to to immutable.
This variant is complicated a bit, you simply can use dirtyMap.map(...).toMap
as Debojit Paul mentioned.
Another variant is foldLeft
:
dirtyMap.foldLeft(Map[String, Set[String]]())(
(map, entry) => map + (entry._1 -> entry._2.toSet)
)
You specify accumulator, which is immutable.Map
and you add each entry to this map with converted Set.
As for me, I think using foldLeft
is more effective way.
Upvotes: 0