如何find一个Scalastring是否可parsing为Double或不?
假设我在scala中有一个string,我想试图parsing一个双精度。
我知道,我可以调用toDouble
,然后捕获Java的NUM格式exception,如果失败,但有没有更干净的方法来做到这一点? 例如,如果有一个返回Option[Double]
的parseDouble
函数,这将有资格。
我不想把它放在我自己的代码中,如果它已经存在于标准库中,我只是在错误的地方寻找它。
感谢您的任何帮助,您可以提供。
要不就
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)
Scalaz在String
上提供了一个扩展方法parseDouble
,它给出了Validation[NumberFormatException, Double]
types的值。
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
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
你可以尝试使用util.control.Exception.catching
,它返回一个Either
types。
所以使用下面的方法返回一个包装NumberFormatException
的Left或一个包装Double
的Right
import util.control.Exception._ catching(classOf[NumberFormatException]) either "12.W3".toDouble
这不仅仅是在Scala中,甚至在基本的Java中也是如此。
尽pipe这里有一段代码,但没有例外 :
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")
不幸的是,这不在标准库中。 以下是我使用的:
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)
我通常会去“就地”尝试:
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中进行进一步计算,并且任何exception都将投影到Failure(ex)中。 AFAIK这是处理一系列不可靠操作的惯用方式。