Подтвердить что ты не робот

Scala: преобразовать строку в Int или None

Я пытаюсь получить число из поля xml

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

с помощью

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

Иногда может быть не значение в xml. Текст будет "", и это вызовет исключение java.lang.NumberFormatException.

Что такое чистый способ получить либо Int, либо None?

4b9b3361

Ответ 1

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

Ответ 2

Дополнительная заметка об использовании после принятого ответа. После import scala.util.Try рассмотрим

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

или аналогично, но в более сложной форме, которая учитывает только соответствующее исключение при преобразовании в интегральные значения, после import java.lang.NumberFormatException,

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

Таким образом,

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

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

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

Ответ 3

Вот еще один способ сделать это, который не требует написания вашей собственной функции и который также можно использовать для подъема до 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 хорошая запись в блоге по этому вопросу.)