在任何情况下调用 .toDouble 并返回选项[Double]



好奇是否有人在以下方面有创造性的方法:

def toDouble(any: Any): Option[Double] = // { if any has a .toDouble method call it else return None }

例如,Int,String,Long都有一个.toDouble方法。如果它存在(即使是非基元类型(,我希望它被调用。

理想情况下是这样的(没有 .toString'先处理所有内容(

def toDouble(any: Any): Option[Double] = {
  case any.hasToDouble => Try(any.toDouble).toOption
  case _ => None
}
您可以使用

def doubleFromAny(in: Any): Option[Double] = {
  Try{in.asInstanceOf[{def toDouble: Double}].toDouble}.toOption
}

这样做的问题是通过隐式提供的任何toDouble都不起作用(因此字符串"4.5"会给你None(。 我也预计性能不会很好。

最后,你需要弄清楚哪些类型是可能的,并使用乔恩·安德森的答案来检查和投射每种类型。

您可以使用模式匹配。 这还有一个额外的好处,即您可以更明确地控制转换方式。 (例如,如果您想尝试额外的字符串解析(

def toDouble(any: Any): Option[Double] = {
  any match {
    case n:Int => Some(n.toDouble)
    case n:Long => Some(n.toDouble)
    case n:Double => Some(n.toDouble)
    case s:String => Try(s.toDouble).toOption
    case _ => None
  }
}
  def toDouble(a: Any): Option[Double] = try {
    if (a == null) None else {
      Some(a.toString.toDouble)
    }
  } catch {
    case scala.util.control.NonFatal(e) => None
  }

其他人提出了很好的答案。我想到的另一种方法是使用隐式对象。对于上面的例子,你可以写一些东西:

sealed trait ImplicitType[T]
object ImplicitType{
  implicit object IntType extends ImplicitType[Int]
  implicit object StringType extends ImplicitType[String]
  implicit object LongType extends ImplicitType[Long]
  implicit object DoubleType extends ImplicitType[Double]
}
def toDouble[T : ImplicitType](n: T) : Option[Double] = {
  Try(n.toString.toDouble).toOption
}

上述工作是因为编译器约束来自ImplicitType配套对象中隐式对象的可用性。上下文绑定隐式 def f: ImplicitType[T] 默认搜索 ImplicitType 的配套对象内的隐式对象。所以现在你可以做这样的事情:

val foo = toDouble(1) // Some(1.0)
val foo1 = toDouble("2") //Some(2.0)
val foo2 = toDouble(1L) //Some(1.0)
val foo3 = toDouble("s") //None
val foo4 = toDouble(1.23456e300d) //Some(1.23456E300)

这样,您的toDouble功能根本不会改变。我想不出避免toString抱歉的方法。希望这对你有用。

最新更新