Scala: преобразовать строку в Int или None
Я пытаюсь получить число из поля xml
...
<Quantity>12</Quantity>
...
с помощью
Some((recipe \ "Main" \ "Quantity").text.toInt)
Иногда может быть не значение в xml. Текст будет ""
, и это вызовет исключение java.lang.NumberFormatException.
Что такое чистый способ получить либо Int, либо None?
Ответы
Ответ 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 хорошая запись в блоге по этому вопросу.)