web-dev-qa-db-ja.com

マップのキーとして値Aを使用してSeq [A]をMap [Int、A]に変換する方法は?

次のようなクラスのオブジェクトを含むSeqがあります。

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

次に、各オブジェクトのSeq値をキーとして使用し、オブジェクト自体を値として使用して、このMapkeyに変換します。そう:

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

Scala 2.8でこれを効率的かつエレガントな方法で行うにはどうすればよいですか?

40
Jesper

Seqをマッピングして、一連のタプルを生成します。次に、それらのタプルを使用してMapを作成します。 Scalaのすべてのバージョンで動作します。

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

2.8以降Scalaは.toMap、 そう:

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

または、タプルの中間シーケンスの構築を回避することに夢中なら:

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

もう1つの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)))

重複するキーがある場合、マップの作成中にそれらの一部を破棄することに注意してください! 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))))
7
retronym

scalaは2つのタプルをマップに変換することを知っているので、最初にseqをタプルに変換してからマップすることをお勧めします(この場合、intであるかどうかは関係ありません)文字列、文字列):

一般的なアルゴリズムは次のとおりです。

  1. Seqの各アイテム
  2. アイテム->タプル(キー、値)
  3. タプルごと(キー、値)
  4. Map(key、value)に集約

または要約すると:

ステップ1:Seq-> 2つのタプル

ステップ2:2つのタプル->マップ

例:

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)
2
Tomer Ben David