2013-10-10 10 views
6

Beim Versuch, alle Unit -() aus einer Liste zu entfernen, habe ich versucht, toMap aufrufen.Kann nicht beweisen, dass Unit <: <(T, U)

scala> List((),()).filter(_ !=()).toMap 
<console>:8: error: Cannot prove that Unit <:< (T, U). 
       List((),()).filter(_ !=()).toMap 
             ^

Was bedeuten diese Fehler?

Für eine List, möchte ich eine Karte aller Tupel (String, String) für Nicht-Unit-Elemente erstellen, aber einige der Werte können null sein.

scala> val x = List((),(), (3,4)).filter(_ !=()).toMap 
<console>:7: error: Cannot prove that Any <:< (T, U). 
     val x = List((),(), (3,4)).filter(_ !=()).toMap 
               ^

scala> val x = List((),(), (3,4)).filter(_ !=()) 
x: List[Any] = List((3,4)) 

scala> x.toMap 
<console>:9: error: Cannot prove that Any <:< (T, U). 
       x.toMap 
       ^

Antwort

4

Ah! Jetzt macht your other question ein wenig mehr Sinn. Immer noch nicht sicher, was Sie obwohl gemischte diese Unit/Tuple2 Liste zu produzieren tun.

sollte diese Arbeit:

List((),(), (3,4)).collect { case [email protected](_: Int, _: Int) => t }.toMap 

Bitte beachte, dass ich variable binding hier bin mit (dem Spiel zu t Bindung) die gleiche Tuple2 Instanz wir abgestimmt eher zurück, als einen neuen zu schaffen.

von collect mit konvertieren Sie die Art Ihrer Liste List[Any]-List[(Int, Int)], das ist das, was toMap will, da es einige List[(A,B)] erwartet wird.


Anmerkung: Obwohl diese Antwort sollte für Sie arbeiten, ich denke immer noch, Ihr Design ist fehlerhaft. Sie wären besser dran, die zugrunde liegenden Konstruktionsfehler Festsetzung anstatt die Symptome wie diese zu behandeln.

Es sieht aus wie das ist eine gute Passform für die Verwendung von Scala's Option type wäre. In diesem Fall würde Ihre Beispielliste List(None, None, Some((3,4))) werden, oder man könnte es als List(None, None, Some(3->4)) zur besseren Lesbarkeit schreiben (verschachtelte Klammern so verwirrend sein können).

Wenn Sie Option verwenden dann die Art der Liste wird List[Option[(Int, Int)]], die viel schöner sein sollte, behandeln als ein List[Any]. Um loszuwerden der None Einträge und erhalten die gewünschte List[(Int,Int)] Sie können flatten einfach anrufen:

List(None, None, Some(3->4)).flatten 
// res0: List[(Int, Int)] = List((3,4)) 
List(None, None, Some(3->4)).flatten.toMap 
// res1: scala.collection.immutable.Map[Int,Int] = Map(3 -> 4) 

Allerdings wäre es noch besser wenn können Sie die None Einträge in der Liste in der ersten Umsetzung vermeiden Ort.Wenn Sie diese Liste zum Verständnis mit einer Scala erstellen, können Sie die ungültigen Elemente aus der Ausgabe entfernen, indem Sie use a guard in your for expression eingeben.

+0

Dank für mein fehlerhaftes Design Hinweis. Ich benutze 'None''sb/c, wenn ich einen for-Ausdruck benutze, um über eine 'List [JsObject]' zu iterieren, muss ich ein Feld (glaube ich) als Teil der 'yield (.. .'). Mein Code sieht folgendermaßen aus: 'for {jsObj <- jsonObjs; val x = ... 'wo der Rückgabetyp ist: List [Option (String, JsValue)]'. Ist es möglich, Werte in einem Ausdruck zu "überspringen"? Für Werte, die ich überspringen muss, gebe ich 'None' zurück. –

+1

@Kevin - Ja, Sie können Werte überspringen. Das ist, was mein Kommentar über die Verwendung einer Wache im Verständnis war. Lesen Sie die Beispiele in dem Blog, mit dem ich verlinkt habe, und es sollte klar sein, wie das geht. Übrigens hatte ich ähnliche Probleme, als ich das erste Mal für Scala schrieb. Nachdem ich gelernt hatte, wie man Wachen und den 'Nothing'-Typ einsetzt, konnte ich viel tun, um meinen Code aufzuräumen! – DaoWen

1

Es bedeutet, dass der Typ eines Elements in der Liste nicht als Tupel angesehen werden, die eine Karte aufzubauen erforderlich ist. Eine Karte in gewisser Hinsicht ist eine Sammlung von Tupeln (und mehr).

Illustration:

scala> List(1).toMap 
<console>:8: error: Cannot prove that Int <:< (T, U). 
      List(1).toMap 
       ^
scala> List(1 -> 2).toMap 
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) 

ich eine Karte aus einer Liste von Tupeln aufbauen können, aber nicht aus einer Liste von einzelnen Mächtigkeit Elemente.

Vielleicht meinen Sie .map statt .toMap zu sagen? ;)

1

Alles in einem Rutsch:

scala> val l2 = List(1 -> 3,(), 4 -> 4,(), 9 -> 4,(), 16 -> 7) 
l2: List[Any] = List((1,3),(), (4,4),(), (9,4),(), (16,7)) 

scala> (l2 collect { case (a, b) => (a, b) }).toMap 
res4: scala.collection.immutable.Map[Any,Any] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7) 

besser getippt:

scala> (l2 collect { case (i: Int, j: Int) => (i, j) }).toMap 
res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7) 
+0

also wäre die 'besser typisierte' Antwort nur notwendig, wenn ich nur eine' Map [Int, Int] 'erstellen wollte, oder? –

+1

Sie sollten 'Any' so viel wie möglich vermeiden! –

Verwandte Themen