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

前端 未结 7 1202
栀梦
栀梦 2020-12-15 07:37

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

相关标签:
7条回答
  • 2020-12-15 08:02

    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
    
    0 讨论(0)
  • 2020-12-15 08:06

    In addition to the existing answers,

    Map() ++ set.view.map(i => i -> f(i))
    

    is pretty short and performs as well as the faster answers (fold/breakOut).

    (Note the view to prevent creation of a new collection; it does the remapping as it goes.)

    0 讨论(0)
  • 2020-12-15 08:09

    As with all great languages, there's a million ways to do everything.

    Here's a strategy that zips the set with itself.

    val s = Set(1,2,3,4,5)
    Map(s.zip(s.map(_.toString)).toArray : _*)
    

    EDIT: (_.toString) could be replaced with some function that returns something of type V

    0 讨论(0)
  • 2020-12-15 08:11

    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.

    0 讨论(0)
  • 2020-12-15 08:13

    Without definition of func(i: Int) using "string repeating" operator *:

    scala> s map { x => x -> x.toString*2 } toMap
    res2: scala.collection.immutable.Map[Int,String] = Map(2 -> 22, 3 -> 33, 5 -> 55)
    
    0 讨论(0)
  • 2020-12-15 08:14

    The other solutions lack creativity. Here's my own version, though I'd really like to get rid of the _.head map.

    s groupBy identity mapValues (_.head) mapValues func
    
    0 讨论(0)
提交回复
热议问题