Scala: отобразить карту в список кортежей

Я попытался использовать 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))

Обратите внимание, как создается List для отдельных элементов (r1), но создается карта для кортежей (r3). Даже не заставляя обрабатываемый тип (r2). Только явный вызов Seq сделал это (r4). Итак, мой вопрос: почему/как MapMap "автоматически" создает новую карту, а не список, например? На самом деле, как определяется тип возврата (Seq, List и т.д.)

Ответ 1

A Map уже есть набор кортежей.

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

Когда вы сопоставляете Map, вы сопоставляете пары (ключ, значение), которые он содержит. Это не может работать, потому что вы удаляете ключи и сохраняете только значения. Итак, у вас уже нет Map, но на два или три иерархии коллекции, 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))

Здесь Seq более обобщен, чем List:

val r4 = m.toSeq

Простым решением, описанным в @EndeNeu, является просто использование toList. Когда вы Map собираете, он должен вернуть исходный тип коллекции, если это возможно. Таким образом, сопоставление Map должно возвращать еще один Map, если только базовая структура не сделала это Map (например, полностью удаление ключей) в r1.