2015-02-27 13 views
10

Ich versuchte Map.map zu verwenden, um eine Karte in eine Liste von Tupeln zu konvertieren. Dies schlägt jedoch fehl. Ich habe die folgenden Versuche:Scala: Karte eine Karte zur Liste von Tupeln

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)) 

Beachten Sie, wie eine Liste für einzelne Elemente erzeugt wird (R1), sondern eine Karte für Tupel (r3) hergestellt. Nicht einmal zwangsweise arbeitete der Typ (r2). Nur ein expliziter Aufruf von Seq tat es (r4) Also meine Frage ist, warum/wie funktioniert Map.map „automagically“ eine neue Karte und keine Liste zum Beispiel erstellen? In der Tat, wie ist der Rückgabetyp bestimmt (Seq, List, etc.)

+6

Was mit 'm.toList' falsch ist? Beachten Sie auch, dass das Mapping für eine Sammlung eine andere Sammlung desselben Typs zurückgibt, so dass Sie eine Listenzuordnung für eine 'Map' nicht wirklich zurückgeben können, es sei denn, Sie rufen' .toList' darauf auf. –

+0

@Ende - Nichts ist falsch. Siehe Kommentar unten. – user2051561

Antwort

14

A Map ist eine Sammlung von Tupel bereits.

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

Wenn Sie eine Map abbildet, Sie Zuordnung der (Schlüssel, Wert) -Paare, die es enthält. Dies kann nicht funktionieren, weil Sie die Schlüssel entfernen und nur die Werte beibehalten. Also, was Sie haben, ist nicht mehr ein Map, sondern ein oder zwei Schritte auf der Sammlungshierarchie, eine Iterable:

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

den Typ Erzwingen kann nicht funktionieren, weil ein Map[A, B] ist kein List[(A, B)]. Dies entspricht m.map(identity). Beachten Sie, wie Sie selbst e mit Tupel Accessoren Zugriff:

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

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

Hier Seq allgemeinere ist als List:

val r4 = m.toSeq 

Die einfache Lösung, wie durch @EndeNeu angegeben ist, nur toList zu verwenden. Wenn Sie eine Sammlung map, sollte es die ursprüngliche Sammlung Typ zurückgeben, wenn er kann. So Abbilden ein Map sollte eine andere Map zurückkehren, es sei denn, die zugrunde liegende Struktur nicht mehr ein Map (wie das Entfernen Schlüssel vollständig) in r1 gemacht hat.

+0

Danke m-z. Meine Frage ist wirklich: im Falle von 'r1', wie kann' Map' wissen, dass es in eine 'Liste' umgewandelt werden soll? Es könnte etwas anderes sein? Warum nicht ein Array? Ich gehe davon aus, dass hier eine implizite Umwandlung stattfindet. Daher meine Prüfung durch Erzwingen von Typen. In Bezug auf die Tupel, macht Sinn. Das ist die Kartenkonvention. – user2051561

+0

@ user2051561 Es konvertiert es nicht zu einer 'List' in' r1' - es gibt 'Iterable' zurück, da dies das nächste Merkmal in der Hierarchie ist, das mit dem Typ der Sammlung übereinstimmt, die Sie haben. 'Map' erweitert' Iterable'. –