Scala:如何从Set [K]和从K到V的函数创建Map [K,V]?

aio*_*obe 14 functional-programming scala scala-collections

什么是创造一个最好的方式Map[K,V]从一个Set[K]从和功能KV

例如,假设我有

scala> val s = Set(2, 3, 5)
s: scala.collection.immutable.Set[Int] = Set(2, 3, 5)
Run Code Online (Sandbox Code Playgroud)

scala> def func(i: Int) = "" + i + i
func: (i: Int)java.lang.String
Run Code Online (Sandbox Code Playgroud)

什么是最简单的创建方式 Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")

dby*_*rne 21

你可以使用foldLeft:

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

这将比Jesper的解决方案表现更好,因为在一次通过中foldLeft构建Map.Jesper的代码首先创建一个中间数据结构,然后需要将其转换为final Map.

更新:我写了一个微基准测试每个答案的速度:

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

看起来它们几乎都是一样的,只要你避免构建一个中间数据结构.


Jes*_*per 16

那这个呢:

(s map { i => i -> func(i) }).toMap
Run Code Online (Sandbox Code Playgroud)

这会将元素映射s到元组(i, func(i)),然后将生成的集合转换为Map.

注意:i -> func(i)是一样的(i, func(i)).

dbyrne建议首先创建一个集合的视图(请参阅他的答案和评论),这样可以防止创建中间集合,从而提高性能:

(s.view map { i => i -> func(i) }).toMap
Run Code Online (Sandbox Code Playgroud)


Eas*_*sun 7

scala> import collection.breakOut
import collection.breakOut

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

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

scala> val map: Map[Int,String] = set.map(i => i -> func(i))(breakOut)
map: Map[Int,String] = Map(2 -> 22, 3 -> 33, 5 -> 55)

scala>
Run Code Online (Sandbox Code Playgroud)


Rex*_*err 6

除了现有的答案,

Map() ++ set.view.map(i => i -> f(i))
Run Code Online (Sandbox Code Playgroud)

非常简短,表现更快(折叠/ breakOut).

(注意视图以防止创建新集合;它会在重新映射时执行.)