Is there a method to do the following without doing both methods: find
and map
?
val l = 0 to 3
l.find(_ * 33 % 2 == 0).map(_ * 33) // returns Some(66)
Is there a method to do the following without doing both methods: find
and map
?
val l = 0 to 3
l.find(_ * 33 % 2 == 0).map(_ * 33) // returns Some(66)
How about using collect?
// Returns List(66)
List(1, 2, 3) collect { case i if (i * 33 % 2 == 0) => i * 33 }
However that will return all matches and not just the first one.
The better answer would have been, based on Scala 2.9:
// Returns Some(66)
List(1, 2, 3) collectFirst { case i if (i * 33 % 2 == 0) => i * 33 }
The solution suggested in the comments to append a head
to get a Scala 2.8 version of that is not very efficient, I'm afraid. Perhaps in that case I would stick to your own code. In any case, in order to make sure it returns an option, you should not call head
, but headOption
.
// Returns Some(66)
List(1, 2, 3) collect { case i if (i * 33 % 2 == 0) => i * 33 } headOption
collect
will return multiple matches, while find
returns just one. –
Leggat collectFirst
method. Otherwise, as Daniel's comment is alluding to, you will need to use headOption
in addition to collect
to get the same type and behaviour as the original example. –
Pisci guard
–
Rosemarie i*33
twice in each case. Is that possible to do once? –
Archine If you don't want to do your map()
operation multiple times (for instance if it's an expensive DB lookup) you can do this:
l.view.map(_ * 33).find(_ % 2 == 0)
The view
makes the collection lazy, so the number of map()
operations is minimized.
Hey look, it's my little buddy findMap
again!
/**
* Finds the first element in the list that satisfies the partial function, then
* maps it through the function.
*/
def findMap[A,B](in: Traversable[A])(f: PartialFunction[A,B]): Option[B] = {
in.find(f.isDefinedAt(_)).map(f(_))
}
Note that, unlike in the accepted answer, but like the collectFirst
method mentioned in one of its comments, this guy stops as soon as he finds a matching element.
Traversable
already defines the method collectFirst
which does exactly what your findMap
does. –
Electrobiology This can do it, but it would be easier if you tell what you're really trying to achieve:
l.flatMap(n => if (n * 33 % 2 == 0) Some(n * 33) else None).headOption
© 2022 - 2024 — McMap. All rights reserved.