如何将任意数字转换为Double?

8
我需要进行一些原始数据的解析,但是我被迫使用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中有更好的处理方法吗?
5个回答

11

如果在编译时失去类型信息,就像你的情况一样,由于其要求输入类型为Any,那么在运行时检查expectedNumber并使用isInstanceOf方法是唯一的选项。

这被你提出的解决方案中的类型模式匹配实现所掩盖。我认为这是你情况下最好的解决方案。

然而,有一种替代方案是使用Try方法,并将其转换为Option类型。例如:

Try(expectedNumber.toString.toDouble).toOption

在很多方面,那是一个肮脏的解决方案(完全不高效,使用异常来控制流程,...),所以我肯定会使用你的第一种方法


4

这个答案所示,您当然可以使用java.lang.Number来匹配您的情况类型。

def extractDouble(x: Any): Option[Double] = x match {
  case n: java.lang.Number => Some(n.doubleValue())
  case _ => None
}

请注意,对于BigDecimalBigInteger的实例同样适用,无论是scala.math.BigDecimal还是java.math.BigDecimal

2

我曾经使用过原帖作者的解决方案。但是当我遇到一些略微损坏的数据输入时,我随后改用原帖作者的解决方案和 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 这一行代码可能会帮助你省去一些调试和头疼的时间。


1
从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

0

这并没有完全回答提问者的问题。他们说他们被迫使用Any参数,并且仅在您拥有String时才有效(当然很容易实现,但偏离了原始问题)。 - Adowrath
这是一个很好的观点...parseDouble可以修改为def parseDouble(s: Any): Option[Double] = Try { s..toString.toDouble }.toOption - Sumon Rahman
但是,它与Pablo大致相同,但没有解释为什么这是一个不好的想法的警告。 - Adowrath
1
完全同意这是Palbo的扩展...我只是想分享一下链接,里面有一些例子,如果有帮助的话。 - Sumon Rahman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接