2014-11-06 204 views
2

我需要在读取数据文件后将某些字符串值转换为Ints。该字段可能为空,这会在尝试执行转换时导致错误。有没有简单的方法来检查空(或可以转换为整数的适当的值),并只是返回0,如果它不能被转换? getOrElse似乎是一种可能性,但我无法完成工作。我可以写一个很容易做到的功能,但我希望有一个更优雅/简洁的方法来做到这一点。Scala:Succint方法检查空/空值并返回0而不是

回答

8

可以使用Try单子(记录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的链接更多的计算。

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

默认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 
+1

恕我直言,异常对于scala来说太贵了。 – 2014-11-06 17:07:24