Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala return on first Some in list

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.

like image 813
svrist Avatar asked Sep 04 '10 22:09

svrist


People also ask

How to get 1st element of list in Scala?

Coming to list, head() method is used to get the head/top element of the list.

What is getOrElse in Scala?

As we know getOrElse method is the member function of Option class in scala. This method is used to return an optional value. This option can contain two objects first is Some and another one is None in scala. Some class represent some value and None is represent a not defined value.

How do I access elements in Scala list?

We can use the head() and last() methods of the class List to get the first and last elements respectively.


2 Answers

How about:

l.toStream flatMap (myfun andThen (_.toList)) headOption

Stream is lazy, so it won't map everything in advance, but it won't remap things either. Instead of flattening things, convert Option to List so that flatMap can be used.

like image 195
Daniel C. Sobral Avatar answered Oct 02 '22 15:10

Daniel C. Sobral


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 }
like image 23
Xavier Guihot Avatar answered Oct 02 '22 17:10

Xavier Guihot