Reputation: 2064
I am trying to compose two maps and get a composed map in Scala. I am doing the following:
val m1=Map(1->'A',2->'C',3->'Z')
val m2=Map('A' -> "Andy", 'Z'->"Zee",'D'->"David")
val m3=m2.compose(m1)
Now m3 is m1;m2, but its type is Function1.
Question: How can I convert Function1 to Map?
ps.
Here, instead of m2.compose(m1), it is suggested to use val m3 = m1 andThen m2
. Anyways, the result is of type Function1.
Upvotes: 1
Views: 202
Reputation: 6852
Why composing two Maps gives you a Function1
A Map
offers the semantics of a Function1
and then some. When you compose two Map
functions, you get a new Function1
because compose
is an operation on functions.
So you should not expect to get a Map
by composing two Map
s -- you are just composing the function aspects of the Map
s, not the Map
s themselves.
How to get a composed Map
To actually compose two Map
s into another Map
, you can use mapValues
, but be careful. If you do it like this:
val m3 = m1 mapValues m2
you will silently get a view (see this bug) rather than a simple map, so as you do lookups in m3
it will really do lookups in m1
and then in m2
. For large Map
s and few lookups, that's a win because you didn't process a lot of entries you didn't need to. But if you do lots of lookups, this can cause a serious performance problem.
To really make a new single Map
data structure that represents the composition of m1
and m2
you need to do something like
val m3 = (m1 mapValues m2).view.force
That is kind of unfortunate. In a perfect world m1 mapValues m2
would give you the new single composed Map
-- and very quickly, by creating a new data structure with shape identical to m1
but with values run through m2
-- and (m1 mapValues m2).view
would give you the view (and the type would reflect that).
Upvotes: 1
Reputation: 170713
You can also do
val m3: Map[Int, String] = m1.mapValues(m2)
There is a caveat that despite the return type this will recalculate m2(m1(x))
on every access to m3(x)
, just like m2.compose(m1)
.
since I updated the title of the question, the answer does not now directly address the question subject. I will wait to see if somebody possibly provides a direct answer (that is, how to convert Function1 to map).
def funToMap[A, B](f: A => B): Map[A, B] = Map.empty[A, B].withDefault(f)
Upvotes: 1
Reputation: 931
What do you expext for non-existing keys? If yuo want to remove this values from map use
val m1: Map[Int, Char] = Map(1 -> 'A', 2 -> 'C', 3 -> 'Z')
val m2: Map[Char, String] = Map('A' -> "Andy", 'Z' -> "Zee", 'D' -> "David")
val m3: Map[Int, String] = m1.filter(x => m2.contains(x._2)).map(x => x._1 -> m2(x._2))
//Map(1 -> Andy, 3 -> Zee)
Skipping .filter(x => m2.contains(x._2)) with throw an exception for this situations
Upvotes: 2