Find the first element that satisfies condition X in a Seq

If you're confident at least one will format will succeed:

formats.view.map{format => Try(format.parse(str)).toOption}.filter(_.isDefined).head

If you want to be a bit safer:

formats.view.map{format => Try(format.parse(str)).toOption}.find(_.isDefined)

Try was introduced in Scala 2.10.

A view is a type of collection that computes values lazily. It will apply the code within the Try to only as many items in the collection as is necessary to find the first one that is defined. If the first format applies to the string, then it won't try to apply the remaining formats to the string.


You should use find method on sequences. Generally you should prefer built-in methods, because they might be optimised for a specific sequence.

Console println List(1,2,3,4,5).find( _ == 5)
res: Some(5)

That is, to return first SimpleDateFormat that match:

 val str = "1903 January"
 val formats = List("MMM yyyy", "yyyy MMM", "MM yyyy", "MM, yyyy")
   .map(new SimpleDateFormat(_))
 formats.find { sdf => 
      sdf.parse(str, new ParsePosition(0)) != null
 }

 res: Some(java.text.SimpleDateFormat@ef736ccd)

To return first date that has being processed:

val str = "1903 January"
val formats = List("MMM yyyy", "yyyy MMM", "MM yyyy", "MM, yyyy").map(new SimpleDateFormat(_))
val result = formats.collectFirst { 
  case sdf if sdf.parse(str, new ParsePosition(0)) != null => sdf.parse(str)
}

or use lazy collection:

val str = "1903 January"
val formats = List("MMM yyyy", "yyyy MMM", "MM yyyy", "MM, yyyy").map(new SimpleDateFormat(_))
formats.toStream.flatMap { sdf =>
   Option(sdf.parse(str, new ParsePosition(0)))
}.headOption

res: Some(Thu Jan 01 00:00:00 EET 1903)

This prevents the unnecessary evaluations.

formats.collectFirst{ case format if Try(format.parse(str)).isSuccess => format.parse(str) } 

The number of evaluations of the parse method is number of tries + 1.