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

发布于 2024-10-30 17:10:42 字数 496 浏览 3 评论 0原文

Set[K] 创建 Map[K,V] 以及从 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")Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")< /代码>

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")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

不顾 2024-11-06 17:10:42

您可以使用 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。

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

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

看起来它们都是只要避免构建中间数据结构,就几乎相同。

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.

梦巷 2024-11-06 17:10:42

怎么样:

(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

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
喜爱皱眉﹌ 2024-11-06 17:10:42
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>
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>
围归者 2024-11-06 17:10:42

除了现有的答案之外,

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

它还很短,并且执行得与更快的答案(fold/breakOut)一样好。

(请注意该视图以防止创建新集合;它会在进行过程中进行重新映射。)

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.)

舂唻埖巳落 2024-11-06 17:10:42

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

s groupBy identity mapValues (_.head) mapValues func

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
吻泪 2024-11-06 17:10:42

与所有伟大的语言一样,有一百万种方法可以完成所有事情。

这是一个将集合与自身压缩在一起的策略。

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

编辑: (_.toString) 可以替换为一些返回 V 类型的函数

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

夜清冷一曲。 2024-11-06 17:10:42

没有使用“字符串重复”运算符 * 定义 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)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文