如何将Option [String]转换为Option [Int]?

时间:2015-04-30 11:07:49

标签: json scala

我正在阅读并解析一个json文件。 json文件的一个字段是Nullable。它返回一串数字或Null。我需要将字符串转换为int。我能够通过以下代码从String转换为Option [Int],但无法从Option [String]转换为Option [Int]

 def toInt(userId: String):Option[Int] = {
  try {
    Some(userId.toInt)
  } catch {
    case e:Exception => None
  }
}

val user = toInt("abc")

我需要做哪些更改?

5 个答案:

答案 0 :(得分:12)

import util.Try

def toInt(o: Option[String]): Option[Int] =
  o.flatMap(s => Try(s.toInt).toOption)

示例:

scala> toInt(None)
res0: Option[Int] = None

scala> toInt(Some("42"))
res1: Option[Int] = Some(42)

scala> toInt(Some("abc"))
res2: Option[Int] = None

答案 1 :(得分:4)

Option(userId).map(_.toInt)

使用Option代替Some。而不是使用map将其转换为Int

答案 2 :(得分:1)

@Chris Martin和@Michael Zajac的解决方案很好:

import util.Try

def toInt(o: Option[String]): Option[Int] =
  o.flatMap(s => Try(s.toInt).toOption)

但是

如果输入数据经常不正确,则它将使NumberFormatException的生成量增加Try,这对于垃圾收集器来说是不好的。操作后,它需要利用更多的堆栈跟踪。 这意味着我们应该在这里避免使用scala.util.Try

在输入数据经常不正确的情况下,这不是一个简短但性能更高的解决方案:

def toInt(s: Option[String]): Option[Int] = s match {
  case None => None
  case Some(v) if v.isEmpty  => None
  case Some(v) => if (v.forall(_.isDigit) || (v.startsWith("-") && v.drop(1).forall(_.isDigit)))
    Some(v.toInt)
  else
    None
}

测试:

 scala>   toInt(None)
    res0: Option[Int] = None
 scala>   toInt(Some(""))
    res1: Option[Int] = None
 scala>   toInt(Some("42"))
    res2: Option[Int] = Some(42)
 scala>   toInt(Some("-42"))
    res3: Option[Int] = Some(-42)
 scala>   toInt(Some("abc"))
    res4: Option[Int] = None  

摘要:切勿对控制流使用异常!

答案 3 :(得分:0)

您必须map Option对可能包含的值执行某些操作。在代码的上下文中,我会使用flatMap,因为当前方法返回Option,因此我们必须展平嵌套Option的内容。

def toInt(userIdOpt: Option[String]): Option[Int] = userIdOpt flatMap { userId =>
  try {
    Some(userId.toInt)
  } catch {
    case e:Exception => None
  }
}

scala> val u = Option("2")
u: Option[String] = Some(2)

scala> toInt(u)
res0: Option[Int] = Some(2)

scala> toInt(Some("a"))
res4: Option[Int] = None

我们可以使用Try缩短此内容。

import scala.util.Try

def toInt(userIdOpt: Option[String]): Option[Int] =
    userIdOpt.flatMap(a => Try(a.toInt).toOption)

Try(a.toInt)会返回Try[Int],其成功转化为Success[Int],转换失败(不是整数)为Failure[Throwable]Try有一个非常方便的方法toOption,它会将Success(a)转换为Some(a),将Failure转换为None,这正是我们想要的

答案 4 :(得分:0)

Scala 2.13引入了String::toIntOption

flatMap结合使用可提供从Option[String]投射到Option[Int]的安全方法:

Option("1").flatMap(_.toIntOption)            // Option[Int] = Some(1)
(None: Option[String]).flatMap(_.toIntOption) // Option[Int] = None
Option("abc").flatMap(_.toIntOption)          // Option[Int] = None
Option(null: String).flatMap(_.toIntOption)   // Option[Int] = None