如何查找Scala字符串是否可解析为Double?

时间:2012-03-03 00:11:45

标签: scala

假设我在scala中有一个字符串,我想尝试解析它中的双精度数。

我知道,我可以调用toDouble,然后在失败的情况下捕获java num格式异常,但是有更简洁的方法吗?例如,如果有parseDouble函数返回Option[Double],那么这将符合条件。

如果它已经存在于标准库中,我不想把它放在我自己的代码中,我只是在错误的地方寻找它。

感谢您提供的任何帮助。

8 个答案:

答案 0 :(得分:52)

或者只是

def parseDouble(s: String) = try { Some(s.toDouble) } catch { case _ => None }

花哨版:

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)

答案 1 :(得分:31)

Scalaz在parseDouble上提供了一种扩展方法String,其值为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")

如果需要,您可以将其转换为Option

scala> "34.bad".parseDouble.toOption
res36: Option[Double] = None

答案 2 :(得分:19)

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

答案 3 :(得分:10)

您可以尝试使用返回util.control.Exception.catching类型的Either

因此,使用以下内容返回左包装NumberFormatException或右包装Double

import util.control.Exception._

catching(classOf[NumberFormatException]) either "12.W3".toDouble

答案 4 :(得分:6)

不仅在Scala中,甚至在基本的Java中也没有这样的东西。

这是一个代码无异常,但是:

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
}

用法:

implicit val formatter = NumberFormat.getInstance(Locale.ENGLISH)

Console println parseDouble("184.33")
Console println parseDouble("hello, world")

答案 5 :(得分:6)

不幸的是,这不在标准库中。这是我使用的:

class SafeParsePrimitive(s: String) {
  private def nfe[T](t: => T) = {
    try { Some(t) }
    catch { case nfe: NumberFormatException => None }
  }
  def booleanOption = s.toLowerCase match {
    case "yes" | "true" => Some(true)
    case "no" | "false" => Some(false)
    case _ => None
  }
  def byteOption = nfe(s.toByte)
  def doubleOption = nfe(s.toDouble)
  def floatOption = nfe(s.toFloat)
  def hexOption = nfe(java.lang.Integer.valueOf(s,16))
  def hexLongOption = nfe(java.lang.Long.valueOf(s,16))
  def intOption = nfe(s.toInt)
  def longOption = nfe(s.toLong)
  def shortOption = nfe(s.toShort)
}
implicit def string_parses_safely(s: String) = new SafeParsePrimitive(s)

答案 6 :(得分:3)

Scala 2.13引入了String::toDoubleOption

"5.7".toDoubleOption                // Option[Double] = Some(5.7)
"abc".toDoubleOption                // Option[Double] = None
"abc".toDoubleOption.getOrElse(-1d) // Double = -1.0

答案 7 :(得分:1)

我通常会选择"到位"尝试:

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!" )
}

请注意,您可以在for中进行进一步计算,任何异常都会投射到Failure(ex)中。 AFAIK这是处理一系列不可靠操作的惯用方法。