I'm trying to fold over a list of Options in order return the first(or last) Some value or None if there aren't any Some values.
scala> val opts = List(None, Some(1), None, Some(2), None)
opts: List[Option[Int]] = List(None, Some(1), None, Some(2), None)
scala> opts foldLeft(None)((a,io) => a match { case None => io; case Some(i) =>
a})
<console>:9: error: object None does not take parameters
opts foldLeft(None)((a,io) => a match { case None => io; case Some
(i) => a})
^
Not sure what I'm doing wrong. Also there is probably a way to do this simpler using a higher order function but nothing from here caught my eye.
Both methods recursively combine items into another item. foldLeft combines items from left one to right one, on the other hand foldRight does this from right one to left one.
Fold and reduce The difference between the two functions is that fold() takes an initial value and uses it as the accumulated value on the first step, whereas the first step of reduce() uses the first and the second elements as operation arguments on the first step.
The foldLeft method takes an associative binary operator function as parameter and will use it to collapse elements from the collection. The order for traversing the elements in the collection is from left to right and hence the name foldLeft. The foldLeft method allows you to also specify an initial value.
The fold method takes two sets of arguments. One contains a start value and the other a combining function. It then steps through the list, recursively applying the function to two operands: an accumulated value and the next element in the list.
Maybe this can solve your problem - the first element:
opts.flatten.headOption
And the last element:
opts.flatten.lastOption
flatten
method will unbox all Option
values in the list and drop all None
values. headOption
/lastOption
will return either Some
for the first/last element in the list or None
if list is empty.
tenshi’s answer is pretty straightforward but for long lists it will attempt to flatten everything as it isn’t lazy. (I think view
won’t help us here either but I’m not quite sure.)
In that case, you could use:
opts.dropWhile(_.isEmpty).headOption.flatMap(identity)
Unfortunately, we cannot use flatten
here as this will return a generic Iterable[Int]
and no Option
, so we have to chose the longer idiom flatMap(identity)
.
Edit: As dave noticed:
opts.find(_.isDefined).flatMap(identity)
would be even better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With