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

时间:2011-04-07 14:39:38

标签: scala functional-programming 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)

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

创建Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")

的最简单方法是什么?

7 个答案:

答案 0 :(得分:20)

您可以使用foldLeft

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

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

更新:我写了micro benchmark来测试每个答案的速度:

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

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

答案 1 :(得分:16)

这个怎么样:

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

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

注意:i -> func(i)(i, func(i))相同。

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

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

答案 2 :(得分: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>

答案 3 :(得分:6)

除现有答案外,

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

非常短,并且表现得和更快的答案(fold / breakOut)。

(注意视图以防止创建新集合;它会按原样重新映射。)

答案 4 :(得分:1)

与所有优秀的语言一样,有一百万种方法可以做任何事情。

这是一个用自己拉动集合的策略。

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

编辑:(_。toString)可以替换为返回类型为V

的函数

答案 5 :(得分:1)

其他解决方案缺乏创造力。这是我自己的版本,虽然我真的想摆脱_.head地图。

s groupBy identity mapValues (_.head) mapValues func

答案 6 :(得分:0)

没有使用“字符串重复”运算符*:

定义func(i:Int)
scala> s map { x => x -> x.toString*2 } toMap
res2: scala.collection.immutable.Map[Int,String] = Map(2 -> 22, 3 -> 33, 5 -> 55)