Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the first element that satisfies condition X in a Seq

Generally, how to find the first element satisfying certain condition in a Seq?

For example, I have a list of possible date format, and I want to find the parsed result of first one format can parse my date string.

val str = "1903 January" val formats = List("MMM yyyy", "yyyy MMM", "MM yyyy", "MM, yyyy")   .map(new SimpleDateFormat(_)) formats.flatMap(f => {try {   Some(f.parse(str)) }catch {   case e: Throwable => None }}).head 

Not bad. But 1. it's a little ugly. 2. it did some unnecessary work(tried "MM yyyy" and "MM, yyyy" formats). Perhaps there is more elegant and idiomatic way? (using Iterator?)

like image 637
Lai Yu-Hsuan Avatar asked Jun 02 '13 14:06

Lai Yu-Hsuan


1 Answers

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) 
like image 93
vitalii Avatar answered Sep 19 '22 01:09

vitalii