【问题标题】:Scala: Succint way to check for null/empty values and return 0 insteadScala:检查空/空值并返回 0 的简洁方法
【发布时间】:2015-01-03 06:38:48
【问题描述】:

读取数据文件后,我需要将一些字符串值转换为 Ints。该字段可能为空,这将在尝试进行转换时导致错误。是否有一种简单的方法来检查 null (或可以转换为整数的适当值),如果不能转换则只返回 0 ? getOrElse 似乎是一种可能性,但我不能完全让它工作。我可以编写一个可以轻松完成的函数,但我希望有一种更优雅/更简洁的方法来做到这一点。

【问题讨论】:

    标签: scala


    【解决方案1】:

    只转换整数值:

    val lines = Seq("123", "42", "sdfd", null, "")  // read strings from anywhere
    
    val result = lines
      .filter(s => Option(s).isDefined)   // drop null values
      .filter(_.matches("\\d+"))          // drop non integer values
      .map(Integer.parseInt)              // convert to int
    
    result: Seq[Int] = List(123, 42)
    

    或者返回0而不是不正确:

    val lines = Seq("123", "42", "sdfd", null, "") // read strings from anywhere
    
    def convert(s: String): Int =
      Option(s)
        .filter(_.matches("\\d+"))
        .map(Integer.parseInt)
        .getOrElse(0)
    
    val result = lines.map(convert)
    
    result: Seq[Int] = List(123, 42, 0, 0, 0)
    

    【讨论】:

      【解决方案2】:

      默认的toInt 函数会引发异常,但您可以提供更安全的版本,返回Option,然后在其上使用getOrElse

      def toInt(s: String): Option[Int] =
        try {
          Some(s.toInt)
        } catch {
          case e: Exception => None
        }
      
      toInt("42").getOrElse(0) // 42
      toInt("foo").getOrElse(0) // 0
      

      您也可以使用scalaz,它在String 上提供parseInt 方法,该方法返回Validation[NumberFormatException, Int],您可以将其转换为Option。示例:

      "42".parseInt.toOption.getOrElse(0) // 42
      "foo".parseInt.toOption.getOrElse(0) // 0
      

      【讨论】:

      • 恕我直言,异常对于 scala 来说太昂贵了。
      【解决方案3】:

      您可以使用Try monad(记录在here),它有一个getOrElse 方法:

      import scala.util.Try
      val zero = Try { "foo".toInt }.getOrElse(0)
      val leet = Try { "1337".toInt }.getOrElse(0)
      
      val parseOrZero: String => Int = x => Try(x.toInt) getOrElse 0
      val lines = Seq("123", "42", "sdfd", null, "")
      lines.map(parseOrZero)
      ->> res0: Seq[Int] = List(123, 42, 0, 0, 0)
      

      或在线:

      lines.map(x => Try(x.toInt) getOrElse 0)
      

      Try 也有一个toOption 方法,如果成功则获得Some(value),如果异常则获得None。所以,如果你想过滤掉坏条目而不是返回0,你可以这样做:

      lines.flatMap(x => Try(x.toInt).toOption)
      

      Try 还具有所有有用的一元转换,例如 mapflatMap,用于链接更多计算。

      【讨论】:

        猜你喜欢
        • 2019-03-14
        • 1970-01-01
        • 2019-11-06
        • 1970-01-01
        • 2011-08-08
        • 2014-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多