Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

check "isDefined" and map to "get" together

How can I do the following more efficiently:

myoptionList.filter(_.isDefined).map(_.get)

This will take two iterations time, is there any better way to do this?

like image 443
Omid Avatar asked Feb 10 '23 14:02

Omid


1 Answers

You have a couple of options. The simplest is probably flatten. Since Option is implicitly convertible to Iterable, you can flatten a list of Options in much the same way you would a list of lists:

myOptionList.flatten

You can also use flatMap in much the same way. Here are a few options:

myOptionList.flatMap(x => x)
myOptionList.flatMap(identity(_))
myOptionList.flatMap(Option.option2Iterable)
myOptionList.flatMap[Int,List[Int]](identity)

You can also use collect. collect takes a PartialFunction as an argument. If a match is found, then the value is mapped according to the function. Otherwise it is filtered out. So here, you could match on just Some(x) and map to x (so that all Nones are filtered out). This option is the most general, and will allow you to apply even more refined logic if you so desire.

myOptionList.collect { case Some(x) => x }

//Example of more complex logic:
myOptionList.collect {
    case Some(x) if x % 2 == 0 => x / 2
}

I'd also like to mention that in general when you have complex logic that takes more than one operation on a list, but you don't want to traverse over the list multiple times, you can use view:

myOptionList.view.filter(_.isDefined).map(_.get) //Will only traverse list once!
like image 94
Ben Reich Avatar answered Feb 16 '23 04:02

Ben Reich