次のようなクラスのオブジェクトを含むSeq
があります。
class A (val key: Int, ...)
次に、各オブジェクトのSeq
値をキーとして使用し、オブジェクト自体を値として使用して、このMap
をkey
に変換します。そう:
val seq: Seq[A] = ...
val map: Map[Int, A] = ... // How to convert seq to map?
Scala 2.8でこれを効率的かつエレガントな方法で行うにはどうすればよいですか?
Seq
をマッピングして、一連のタプルを生成します。次に、それらのタプルを使用してMap
を作成します。 Scalaのすべてのバージョンで動作します。
val map = Map(seq map { a => a.key -> a }: _*)
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)
もう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))))
scalaは2つのタプルをマップに変換することを知っているので、最初にseqをタプルに変換してからマップすることをお勧めします(この場合、intであるかどうかは関係ありません)文字列、文字列):
一般的なアルゴリズムは次のとおりです。
または要約すると:
ステップ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)