scala return on first Some in list

Viewed 7761

I have a list l:List[T1] and currently im doing the following:

myfun : T1 -> Option[T2]
val x: Option[T2] = l.map{ myfun(l) }.flatten.find(_=>true)

The myfun function returns None or Some, flatten throws away all the None's and find returns the first element of the list if any.

This seems a bit hacky to me. Im thinking that there might exist some for-comprehension or similar that will do this a bit less wasteful or more clever. For example: I dont need any subsequent answers if myfun returns any Some during the map of the list l.

5 Answers

In addition to using toStream to make the search lazy, we can use Stream::collectFirst:

List(1, 2, 3, 4, 5, 6, 7, 8).toStream.map(myfun).collectFirst { case Some(d) => d }
// Option[String] = Some(hello)
// given def function(i: Int): Option[String] = if (i == 5) Some("hello") else None

This:

  • Transforms the List into a Stream in order to stop the search early.

  • Transforms elements using myFun as Option[T]s.

  • Collects the first mapped element which is not None and extract it.

Starting Scala 2.13, with the deprecation of Streams in favor of LazyLists, this would become:

List(1, 2, 3, 4, 5, 6, 7, 8).to(LazyList).map(function).collectFirst { case Some(d) => d }
Related