2014-05-22 17 views
29

Sto cercando di ottenere un numero di un campo XMLScala: convertire la stringa in int o Nessuno

... 
<Quantity>12</Quantity> 
... 

via

Some((recipe \ "Main" \ "Quantity").text.toInt) 

A volte non ci può essere un valore nel xml, anche se . Il testo sarà "" e questo genera una java.lang.NumberFormatException.

Che cos'è un modo pulito per ottenere un Int o un None?

+0

Eventuali duplicati di [Scala è un parseable stringa come un doppio] (http://stackoverflow.com/questions/9542126/scala-is-a- string-parseable-as-a-double) – thSoft

risposta

52
scala> import scala.util.Try 
import scala.util.Try 

scala> def tryToInt(s: String) = Try(s.toInt).toOption 
tryToInt: (s: String)Option[Int] 

scala> tryToInt("123") 
res0: Option[Int] = Some(123) 

scala> tryToInt("") 
res1: Option[Int] = None 
+5

Se stai analizzando molte stringhe vuote, potresti volerle catturare esplicitamente invece di lanciare un'eccezione ogni volta: 'if (s.isEmpty) Nient'altro Prova (s.toInt) .toOption'. –

8

Più di una nota a margine sull'uso dopo la risposta accettata. Dopo import scala.util.Try, non

implicit class RichOptionConvert(val s: String) extends AnyVal { 
    def toOptInt() = Try (s.toInt) toOption 
} 

o simile, ma in un po forma più elaborata che affronta solo l'eccezione rilevante nella conversione su valori interi, dopo import java.lang.NumberFormatException,

implicit class RichOptionConvert(val s: String) extends AnyVal { 
    def toOptInt() = 
    try { 
     Some(s.toInt) 
    } catch { 
     case e: NumberFormatException => None 
    } 
} 

Così,

"123".toOptInt 
res: Option[Int] = Some(123) 

Array(4,5,6).mkString.toOptInt 
res: Option[Int] = Some(456) 

"nan".toInt 
res: Option[Int] = None 
5

Ecco un altro modo per farlo che non richiede la scrittura della propria funzione e che può essere utilizzato anche per sollevare fino a Either.

scala> import util.control.Exception._ 
import util.control.Exception._ 

scala> allCatch.opt { "42".toInt } 
res0: Option[Int] = Some(42) 

scala> allCatch.opt { "answer".toInt } 
res1: Option[Int] = None 

scala> allCatch.either { "42".toInt } 
res3: scala.util.Either[Throwable,Int] = Right(42) 

(A nice blog post sull'argomento.)

+0

Il tuo esempio finale non darà questo risultato. Sembra un errore cut-n-paste. – jwvh

+0

oops. Grazie. l'ho cambiato solo perché la sinistra era fastidiosamente lunga. – Caoilte

Problemi correlati