web-dev-qa-db-ja.com

Scala:Mapをタプルのリストにマッピングする

Map.mapを使用して、マップをタプルのリストに変換しようとしました。ただし、これは失敗します。私は次の実験をしました:

val m = Map(("a" -> 1), ("b" -> 2))
         //> m  :     scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
val r1 = m.map{ case (k,v) => v}                //> r1  : scala.collection.immutable.Iterable[Int] = List(1, 2)
def toTuple[A,B](a:A,b:B) = (a,b)               //> toTuple: [A, B](a: A, b: B)(A, B)
//val r2: List[Tuple2[_,_]] = m.map(e => (e._1,e._2))
val r3 = m.map(e => toTuple(e._1,e._2))         //> r3  : scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
val r4 = m.toSeq                                //> r4  : Seq[(String, Int)] = ArrayBuffer((a,1), (b,2))

リストは単一の要素(r1)に対して生成されますが、マップはタプル(r3)に対して生成されることに注意してください。タイプを強制することもできませんでした(r2)。 Seqへの明示的な呼び出しのみがそれを行いました(r4)だから私の質問は、なぜ/どうやってMap.mapがリストではなく新しいMapを「自動的に」作成するのですか?実際、戻り値の型はどのように決定されますか(Seq、Listなど)

14
user2051561

Mapはすでにタプルのコレクションです。

_scala> "b" -> 2
res0: (String, Int) = (b,2) // Implicitly converted to a Tuple
_

Mapをマッピングするときは、それに含まれる(キー、値)のペアをマッピングします。キーを取り除き、値のみを保持するため、これは機能しません。つまり、あなたが持っているのはMapではなく、コレクション階層の1つまたは2つ上のステップ、Iterableです。

_val r1 = m.map{ case (k,v) => v} 
_

_Map[A, B]_はList[(A, B)]ではないため、型を強制できません。これはm.map(identity)と同等です。タプルアクセサーを使用してeにアクセスしていることに注意してください。

_val r2: List[Tuple2[_,_]] = m.map(e => (e._1,e._2))

val r3 = m.map(e => toTuple(e._1,e._2))
_

ここでは、SeqListよりも一般化されています。

_val r4 = m.toSeq
_

@EndeNeuで述べられている簡単な解決策は、toListを使用することです。コレクションをmapすると、可能であれば元のコレクションタイプを返す必要があります。そのため、Mapをマッピングすると、_r1_で基本となる構造体がMap(キーを完全に削除するような)にならない限り、別のMapが返されます。

23
Michael Zajac