How to find if a Scala String is parseable as a Double or not?

前端 未结 8 556
鱼传尺愫
鱼传尺愫 2020-12-24 01:49

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

相关标签:
8条回答
  • 2020-12-24 02:23

    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
    
    0 讨论(0)
  • 2020-12-24 02:25

    There's nothing like this not only in Scala, but even in basic Java.

    Here's a piece code that does it without exceptions, though:

    def parseDouble(s: String)(implicit nf: NumberFormat) = {
        val pp = new ParsePosition(0)
        val d = nf.parse(s, pp)
        if (pp.getErrorIndex == -1) Some(d.doubleValue) else None
    }
    

    Usage:

    implicit val formatter = NumberFormat.getInstance(Locale.ENGLISH)
    
    Console println parseDouble("184.33")
    Console println parseDouble("hello, world")
    
    0 讨论(0)
  • 2020-12-24 02:29

    Scalaz provides an extension method parseDouble on Strings, 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
    
    0 讨论(0)
  • 2020-12-24 02:33

    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
    
    0 讨论(0)
  • 2020-12-24 02:42

    I'd usually go with an "in place" Try:

    def strTimesTen (s: String) = for (d <- Try(s.toDouble)) yield d * 10
    
    strTimesTen("0.1") match {
        Success(d) => println( s"It is $d" )
        Failure(ex) => println( "I've asked for a number!" )
    }
    

    Note, that you can do further calculation in the for and any exception would project into a Failure(ex). AFAIK this is the idiomatic way of handling a sequence of unreliable operations.

    0 讨论(0)
  • 2020-12-24 02:43

    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)
    
    0 讨论(0)
提交回复
热议问题