Подтвердить что ты не робот

Как найти, если Scala String обрабатывается как Double или нет?

Предположим, что у меня есть строка в scala, и я хочу попытаться разобрать ее.

Я знаю, что я могу просто вызвать toDouble, а затем поймать исключение формата java num, если это не удается, но есть ли более чистый способ сделать это? Например, если была функция parseDouble, которая вернула Option[Double], это было бы квалифицировано.

Я не хочу помещать это в свой собственный код, если он уже существует в стандартной библиотеке, и я просто ищу его в неправильном месте.

Спасибо за любую помощь, которую вы можете предоставить.

4b9b3361

Ответ 1

Или просто

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)

Ответ 2

Scalaz предоставляет метод расширения parseDouble на String s, который дает значение типа 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

Ответ 3

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

Ответ 4

Вы можете попробовать использовать util.control.Exception.catching, который возвращает тип Either.

Таким образом, используя следующие данные, получим левую упаковку a NumberFormatException или правую упаковку a Double

import util.control.Exception._

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

Ответ 5

Нет ничего подобного не только в 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")

Ответ 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)

Ответ 7

Я обычно бывал с "на месте". Попробуйте:

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 - это идиоматический способ обработки последовательности ненадежных операций.