Scala: convertir une chaîne en Int ou None

J'essaie d'obtenir un nombre dans un champ xml

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

Par

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

Parfois, il peut ne pas y avoir de valeur dans le xml, cependant. Le texte sera "" et cela jette un java.lang.NumberFormatException.

Qu'est-ce qu'un moyen propre d'obtenir un Int ou un None?

33
demandé sur doub1ejack 2014-05-22 19:40:52

4 réponses

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
57
répondu Régis Jean-Gilles 2014-05-22 16:35:12

Plus d'une note de côté sur l'utilisation suivant la réponse acceptée. Après import scala.util.Try, considérez

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

Ou de la même manière, mais sous une forme un peu plus élaborée qui ne traite que l'exception pertinente lors de la conversion en valeurs intégrales, après import java.lang.NumberFormatException,

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

Ainsi,

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

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

"nan".toInt
res: Option[Int] = None
10
répondu elm 2014-05-22 18:41:01

Voici une autre façon de le faire qui ne nécessite pas d'écrire votre propre fonction et qui peut également être utilisée pour passer à 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)

(Un joli blog sur le sujet.)

5
répondu Caoilte 2016-05-31 17:41:46

Scala 2.13 introduit String::toIntOption:

"5".toIntOption                 // Option[Int] = Some(5)
"abc".toIntOption               // Option[Int] = None
"abc".toIntOption.getOrElse(-1) // Int = -1
0
répondu Xavier Guihot 2018-10-01 23:57:49