[英]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
? 从Set[K]
创建Map[K,V]
Set[K]
并从K
到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")
创建Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")
的最简单方法是什么Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")
You can use foldLeft
: 你可以使用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的解决方案表现更好,因为foldLeft
在一次传递中构造Map
。 Jesper's code creates an intermediate data structure first, which then needs to be converted to the final Map
. Jesper的代码首先创建一个中间数据结构,然后需要将其转换为最终的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. 看起来它们几乎都是一样的,只要你避免构建一个中间数据结构。
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
. 这会将s
的元素映射到元组(i, func(i))
,然后将生成的集合转换为Map
。
Note: i -> func(i)
is the same as (i, func(i))
. 注意: i -> func(i)
与(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: dbyrne建议首先创建一个集合的视图(请参阅他的答案和评论),这样可以防止创建中间集合,从而提高性能:
(s.view map { i => i -> func(i) }).toMap
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>
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). 非常简短,表现更快(折叠/ breakOut)。
(Note the view to prevent creation of a new collection; it does the remapping as it goes.) (注意视图以防止创建新集合;它会在重新映射时执行。)
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 编辑:(_。toString)可以替换为返回V类型的函数
The other solutions lack creativity. 其他解决方案缺乏创造力。 Here's my own version, though I'd really like to get rid of the _.head
map. 这是我自己的版本,虽然我真的想摆脱_.head
地图。
s groupBy identity mapValues (_.head) mapValues func
Without definition of func(i: Int) using "string repeating" operator *: 没有使用“字符串重复”运算符*定义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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.