Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: How to create a Map[K,V] from a Set[K] and a function from K to V?

What is the best way to create a Map[K,V] from a Set[K] and function from K to V?

For example, suppose I have

scala> val s = Set(2, 3, 5)
s: scala.collection.immutable.Set[Int] = Set(2, 3, 5)

and

scala> def func(i: Int) = "" + i + i
func: (i: Int)java.lang.String

What is the easiest way of creating a Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")

like image 409
aioobe Avatar asked Apr 07 '11 14:04

aioobe


People also ask

How do I create a 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. Maps are also called Hash tables.

How do I create a map from a list in Scala?

In Scala, you can convert a list to a map in Scala using the toMap method. A map contains a set of values i.e. key-> value but a list contains single values. So, while converting a list to map we have two ways, Add index to list.

What does => mean in Scala?

=> is the "function arrow". It is used both in function type signatures as well as anonymous function terms. () => Unit is a shorthand for Function0[Unit] , which is the type of functions which take no arguments and return nothing useful (like void in other languages).


2 Answers

You can use foldLeft:

val func2 = (r: Map[Int,String], i: Int) => r + (i -> func(i))
s.foldLeft(Map.empty[Int,String])(func2)

This will perform better than Jesper's solution, because foldLeft constructs the Map in one pass. Jesper's code creates an intermediate data structure first, which then needs to be converted to the final Map.

Update: I wrote a micro benchmark testing the speed of each of the answers:

Jesper (original): 35s 738ms
Jesper (improved): 11s 618ms
           dbyrne: 11s 906ms
         Rex Kerr: 12s 206ms
          Eastsun: 11s 988ms

Looks like they are all pretty much the same as long as you avoid constructing an intermediate data structure.

like image 138
dbyrne Avatar answered Oct 22 '22 20:10

dbyrne


What about this:

(s map { i => i -> func(i) }).toMap

This maps the elements of s to tuples (i, func(i)) and then converts the resulting collection to a Map.

Note: i -> func(i) is the same as (i, func(i)).

dbyrne suggests creating a view of the set first (see his answer and comments), which prevents an intermediate collection from being made, improving performance:

(s.view map { i => i -> func(i) }).toMap
like image 30
Jesper Avatar answered Oct 22 '22 22:10

Jesper