2013-10-10 13 views
6

Quando si prova a rimuovere tutto Unit -() da un elenco, ho provato a chiamare toMap.Impossibile provare quell'Unità <: <(T, U)

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

Cosa significa questo errore?

Per un List, mi piacerebbe creare una mappa di tutte le tuple (String, String) per elementi non Unit, ma alcuni valori possono essere nulli.

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 
       ^

risposta

4

Ah! Ora your other question ha un po 'più senso. Non sei ancora sicuro di cosa stia facendo per creare questo elenco misto Unit/Tuple2.

Questo dovrebbe funzionare:

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

Si noti che sto usando qui variable binding (vincolante la partita per t) per restituire la stessa istanza Tuple2 abbiamo fatto coincidere piuttosto che crearne uno nuovo.

Utilizzando collect si converte il tipo di vostra lista List[Any]-List[(Int, Int)], che è quello che vuole toMap dal momento che è in attesa di qualche List[(A,B)].


Nota: Anche se questa risposta dovrebbe funzionare per voi, penso ancora che il vostro disegno è viziata. Faresti meglio a correggere il difetto di progettazione sottostante piuttosto che trattare i sintomi in questo modo.

Sembra che questo sarebbe adatto per l'utilizzo di Scala's Option type. In questo caso, il tuo elenco di campioni diventerebbe List(None, None, Some((3,4))), o potresti scriverlo come List(None, None, Some(3->4)) per la leggibilità (parentesi annidata come quella che può generare confusione).

Se si utilizza Option quindi il tipo della vostra lista diventa List[Option[(Int, Int)]], che dovrebbe essere molto più bello da affrontare che un List[Any]. Per sbarazzarsi dei None voci e ottenere il desiderato List[(Int,Int)] si può chiamare flatten:

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) 

Tuttavia, sarebbe ancora meglio se si può evitare di mettere le None voci presenti nell'elenco nella prima posto.Se stai producendo questo elenco usando Scala per la comprensione, potresti use a guard in your for expression rimuovere gli elementi non validi dall'output.

+0

Grazie per aver ricordato il mio progetto imperfetto. Sto usando 'None''sb/c, quando si usa un'espressione for per iterare su un' List [JsObject] ', ho bisogno di restituire un campo (credo) come parte del' yield di for-expression (.. .'). Il mio codice assomiglia a: 'for {jsObj <- jsonObjs; val x = ... 'dove il tipo di ritorno è' List [Option (String, JsValue)] '. È possibile "saltare" i valori in un'espressione for? Per i valori che ho bisogno di saltare, restituisco 'None'. –

+1

@Kevin - Sì, è possibile saltare i valori. Questo è ciò di cui parlava il mio commento sull'uso di una guardia nella comprensione. Leggi gli esempi sul blog a cui mi sono collegato e dovrebbe essere chiaro come farlo. A proposito, ho avuto problemi simili la prima volta che stavo scrivendo a comprensione per Scala. Dopo aver appreso come sfruttare le protezioni e il tipo "Niente", ero in grado di fare molto per ripulire il mio codice! – DaoWen

1

significa che il tipo di un elemento della lista non può essere visto come una tupla che è necessario per costruire una mappa. Una mappa in un certo senso è una raccolta di tuple (e altro).

Illustrazione:

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) 

posso costruire una mappa da una lista di tuple, ma non da un elenco di elementi singoli cardinalità.

Forse intendete dire .map anziché .toMap? ;)

1

Tutto in un colpo solo:

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) 

Meglio scelto:

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

quindi la risposta 'meglio digitato' sarebbe necessaria solo se volessi creare solo una' Mappa [Int, Int] ', giusto? –

+1

Si consiglia di evitare 'Any' il più possibile! –

Problemi correlati