How to find if a Scala String is parseable as a Double or not?
Suppose that I have a string in scala and I want to try to parse a double out of it.
I know that, I can just call toDouble
and then catch the java num format exception if this fails, but is there a cleaner way to do this? For example if there was a parseDouble
function that returned Option[Double]
this would qualify.
I don't want to put this in my own code if it already exists in the standard library and I am just looking for it in the wrong place.
Thanks for any help you can provide.
For Scala 2.13+ see Xavier's answer below. Apparently there's a toDoubleOption
method now.
For older versions:
def parseDouble(s: String) = try { Some(s.toDouble) } catch { case _ => None }
Fancy version (edit: don't do this except for amusement value; I was a callow youth years ago when I used to write such monstrosities):
case class ParseOp[T](op: String => T)
implicit val popDouble = ParseOp[Double](_.toDouble)
implicit val popInt = ParseOp[Int](_.toInt)
// etc.
def parse[T: ParseOp](s: String) = try { Some(implicitly[ParseOp[T]].op(s)) }
catch {case _ => None}
scala> parse[Double]("1.23")
res13: Option[Double] = Some(1.23)
scala> parse[Int]("1.23")
res14: Option[Int] = None
scala> parse[Int]("1")
res15: Option[Int] = Some(1)
Scalaz provides an extension method parseDouble
on String
s, which gives a value of type Validation[NumberFormatException, Double]
.
scala> "34.5".parseDouble
res34: scalaz.Validation[NumberFormatException,Double] = Success(34.5)
scala> "34.bad".parseDouble
res35: scalaz.Validation[NumberFormatException,Double] = Failure(java.lang.NumberFormatException: For input string: "34.bad")
You can convert it to Option
if so required.
scala> "34.bad".parseDouble.toOption
res36: Option[Double] = None
scala> import scala.util.Try
import scala.util.Try
scala> def parseDouble(s: String): Option[Double] = Try { s.toDouble }.toOption
parseDouble: (s: String)Option[Double]
scala> parseDouble("3.14")
res0: Option[Double] = Some(3.14)
scala> parseDouble("hello")
res1: Option[Double] = None
You could try using util.control.Exception.catching
which returns an Either
type.
So using the following returns a Left wrapping a NumberFormatException
or a Right wrapping a Double
import util.control.Exception._
catching(classOf[NumberFormatException]) either "12.W3".toDouble
Scala 2.13
introduced String::toDoubleOption
:
"5.7".toDoubleOption // Option[Double] = Some(5.7)
"abc".toDoubleOption // Option[Double] = None
"abc".toDoubleOption.getOrElse(-1d) // Double = -1.0