我需要进行一些原始数据解析,并且我被迫使用Any
类型。
如果我读取的数据采用任何数字格式(Int
/ Double
/ Long
/ ...),我需要将其转换为Double
,否则(例如。String
)我需要把它留空。
这就是我提出的:
def extractDouble(expectedNumber: Any): Option[Double] = expectedNumber match {
case i: Int => Some(i.toDouble)
case l: Long => Some(l.toDouble)
case d: Double => Some(d)
case _ => None
}
这显然看起来不太合适。在Scala中有没有更好的方法来解决这个问题?
答案 0 :(得分:8)
一旦您在编译时丢失了类型信息,因为它恰好是您的情况,因为您的输入类型是Any
作为其要求的一部分,没有比检查expectedNumber
更多的选项了运行isInstanceOf
。
您在提议的解决方案中执行的类型模式匹配会掩盖这一点。我认为这是您案例中最好的解决方案。
但是,有一种替代方法是使用Try
并将其转换为Option
。例如:
Try(expectedNumber.toString.toDouble).toOption
这在很多方面都是一个肮脏的解决方案(根本没有效率,使用例外来控制流量......)我会定义地使用你的第一种方法
答案 1 :(得分:3)
如SQL Fiddle回答:
所示,这当然是可能的使用java.lang.Number
与您的案例类型匹配。
def extractDouble(x: Any): Option[Double] = x match {
case n: java.lang.Number => Some(n.doubleValue())
case _ => None
}
请注意,这也适用于BigDecimal
和BigInteger
的实例,无论是scala.math.BigDecimal
还是java.math.BigDecimal
。
答案 2 :(得分:1)
import scala.util.Try
def parseDouble(s: String): Option[Double] = Try { s.toDouble }.toOption
答案 3 :(得分:1)
我正在使用OP的解决方案一段时间。但是在遇到一些稍微损坏的数据输入时,我随后改为OP解决方案和Try
解决方案的组合。
def extractDouble(expectedNumber: Any): Option[Double] = expectedNumber match {
case i: Int => Some(i.toDouble)
case l: Long => Some(l.toDouble)
case d: Double => Some(d)
case s: String => Try(s.trim.toDouble).toOption
case _ => None
}
case s:String
行可能会为您节省一些调试工作,如果您正在处理大而且可能混乱的数据,那么可能会让您感到沮丧
答案 4 :(得分:0)
从Scala 2.13
开始,我们可以将expectedNumber: Any
转换为String
之后应用新的String::toDoubleOption
:
def extractDouble(expectedNumber: Any): Option[Double] =
expectedNumber.toString.toDoubleOption
例如:
extractDouble(12.56d) // Option[Double] = Some(12.56)
extractDouble(12) // Option[Double] = Some(12.0)
extractDouble(12L) // Option[Double] = Some(12.0)
extractDouble("hello") // Option[Double] = None