scala 如何使用 A 的值作为映射中的键将 Seq[A] 转换为 Map[Int, A]?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2925041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:11:27  来源:igfitidea点击:

How to convert a Seq[A] to a Map[Int, A] using a value of A as the key in the map?

scalascala-2.8scala-collections

提问by Jesper

I have a Seqcontaining objects of a class that looks like this:

我有一个Seq包含类的对象,如下所示:

class A (val key: Int, ...)

Now I want to convert this Seqto a Map, using the keyvalue of each object as the key, and the object itself as the value. So:

现在我想将它转换Seq为 a Map,使用key每个对象的值作为键,使用对象本身作为值。所以:

val seq: Seq[A] = ...
val map: Map[Int, A] = ... // How to convert seq to map?

How can I does this efficiently and in an elegant way in Scala 2.8?

我怎样才能在 Scala 2.8 中以优雅的方式高效地做到这一点?

采纳答案by Daniel Spiewak

Map over your Seqand produce a sequence of tuples. Then use those tuples to create a Map. Works in all versions of Scala.

映射您的Seq并生成一系列元组。然后使用这些元组创建一个Map. 适用于所有版本的 Scala。

val map = Map(seq map { a => a.key -> a }: _*)

回答by Seth Tisue

Since 2.8 Scala has had .toMap, so:

自从 2.8 Scala 有了.toMap,所以:

val map = seq.map(a => a.key -> a).toMap

or if you're gung ho about avoiding constructing an intermediate sequence of tuples:

或者,如果您对避免构建元组的中间序列很感兴趣:

val map: Map[Int, A] = seq.map(a => a.key -> a)(collection.breakOut)

回答by retronym

One more 2.8 variation, for good measure, also efficient:

另一个 2.8 变体,为了更好的衡量,也是有效的:

scala> case class A(key: Int, x: Int)
defined class A

scala> val l = List(A(1, 2), A(1, 3), A(2, 1))
l: List[A] = List(A(1,2), A(1,3), A(2,1))

scala> val m: Map[Int, A] = (l, l).zipped.map(_.key -> _)(collection.breakOut)
m: Map[Int,A] = Map((1,A(1,3)), (2,A(2,1)))

Note that if you have duplicate keys, you'll discard some of them during Map creation! You could use groupByto create a map where each value is a sequence:

请注意,如果您有重复的键,您将在地图创建过程中丢弃其中的一些!您可以使用groupBy创建一个地图,其中每个值都是一个序列:

scala> l.groupBy(_.key)
res1: scala.collection.Map[Int,List[A]] = Map((1,List(A(1,2), A(1,3))), (2,List(A(2,1))))

回答by Tomer Ben David

As scala knows to convert a Tuple of two to a map, you would first want to convert your seq to a tuple and then to map so (doesn't matter if it's int, in our case string, string):

由于scala知道将两个元组转换为映射,您首先要将seq转换为元组,然后进行映射(是否为int无关紧要,在我们的示例中为字符串,字符串):

The general algorithm is this:

一般算法是这样的:

  1. For each item in Seq
  2. Item --> Tuple(key, value)
  3. For each tuple(key, value)
  4. Aggregate to Map(key,value)
  1. 对于 Seq 中的每个项目
  2. 项目 --> 元组(键,值)
  3. 对于每个元组(键,值)
  4. 聚合到 Map(key,value)

Or to sum up:

或者总结一下:

Step 1: Seq --> Tuple of two

第 1 步:Seq --> 两个元组

Step 2: Tuple of two --> Map

第 2 步:二元组 --> 映射

Example:

例子:

case class MyData(key: String, value: String) // One item in seq to be converted to a map entry.

// Our sequence, simply a seq of MyData
val myDataSeq = Seq(MyData("key1", "value1"), MyData("key2", "value2"), MyData("key3", "value3")) // List((key1,value1), (key2,value2), (key3,value3))

// Step 1: Convert seq to tuple
val myDataSeqAsTuple = myDataSeq.map(myData => (myData.key, myData.value)) // List((key1,value1), (key2,value2), (key3,value3))

// Step 2: Convert tuple of two to map.
val myDataFromTupleToMap = myDataSeqAsTuple.toMap // Map(key1 -> value1, key2 -> value2, key3 -> value3)