Reputation: 2715
I need to convert some string values to Ints after reading in a data file. It's possible the field will be empty, which will cause an error when it tries to do the conversion. Is there an easy way to check for null (or an appropriate value that can be converted to integer) and just return 0 if it can't be converted? getOrElse seemed to be a possibility but I can't quite get that to work write. I could just write a function that could do it pretty easily but I was hoping there was a more elegant/succinct way to do this.
Upvotes: 2
Views: 6448
Reputation: 16324
You can use the Try
monad (documented here), which has a getOrElse
method:
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)
Or in-line:
lines.map(x => Try(x.toInt) getOrElse 0)
Try
also has a toOption
method, which gets Some(value)
if successful, or None
on exception. So, if you wanted to filter out the bad entries instead of returning 0
, you could do:
lines.flatMap(x => Try(x.toInt).toOption)
Try
also has all the useful monadic transformations like map
and flatMap
for chaining more computation.
Upvotes: 9
Reputation: 10681
Convert only integer value:
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)
Or return 0 instead of incorrect:
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)
Upvotes: 1
Reputation: 108169
The default toInt
function throws an exception, but you can provide a safer version returning an Option
and then use getOrElse
on it
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
Alternatively you can use scalaz
, which provides a parseInt
method on String
which returns a Validation[NumberFormatException, Int]
, which you can turn into an Option
. Example:
"42".parseInt.toOption.getOrElse(0) // 42
"foo".parseInt.toOption.getOrElse(0) // 0
Upvotes: 1