I have a function that receives a String like the following:

"-10.0 -10.0,10.0 10.0,0.0 0.0"

And needs to translate that into a Seq[Coordinate] that would look like this:

    Coordinate(-10.0, -10.0),
    Coordinate( 10.0,  10.0),
    Coordinate(  0.0,   0.0)

Here is the function that I wrote to achieve this:

def toCoordinates(coordinates: String): Seq[Coordinate] = {
  val coordinatesList = coordinates.split(",")
  coordinatesList flatMap { coordinate =>
    coordinate.split("\\s+") match {
      case Array(lat:String, lon:String) => Some(Coordinate(lat.toDouble, lon.toDouble))
      case _                             => None

I see that if someone sends "foo bar" as a coordinate, my code would fail miserably, although I don't see a way to prevent this without some if conditions.

Any idea on how I can implement this check while still having functional code? Or any other tips that might be helpful for a Scala newbie.


Instead of writing lat.toDouble and lon.toDouble, I would use s.split("\\s+").map(_.toDouble) to convert all elements. The type annotation within the match seems excessive to me here.

To discard invalid coordinates such as "foo bar", you would have to catch a NumberFormatException.

Note that split("\\s+") is not tolerant of spaces after commas. For example, " 1.0 2.0".split("\\s+") would produce Array("", "1.0", "2.0"), which would be a three-element array and thus considered invalid.

def toCoordinates(ss: String): Seq[Coordinate] = {
  ss.split(",").flatMap { s =>
    try {
      s.split("(?<!^)\\s+").map(_.toDouble) match {
        case Array(lat, lon) => Some(Coordinate(lat, lon))
        case _               => None       
    } catch {
      case e: NumberFormatException => None

Also you can write more human-readable and understandable algorithm with the help of extractors and method collect:

val Coord = """(.+?)\s+(.+)""".r

object Double { def unapply(s: String) = Try(s.toDouble).toOption }

def parseCoordinates(input: String): Seq[Coordinate] =
  input.split(',') collect {
    case Coord(Double(lat), Double(lan)) => Coordinate(lat, lan)
  • \$\begingroup\$ what does that .r do? The one on the definition of Coord \$\endgroup\$ – Rodrigo Sasaki Jul 18 '16 at 18:50
  • \$\begingroup\$ Method .r creates regular expression (instance of Regex class). "abc".r is equivalent to new Regex("abc"). See description and usage here. \$\endgroup\$ – Nikolay Artamonov Jul 20 '16 at 11:48

Your Answer

