Reputation: 42050
Suppose I have a list xs: List[X]
and functions f(x:X):Y
and g(y):Boolean
. Now I need to find the first y = f(x)
so that g(y) == true
.
def findY(xs: List[X], f: X => Y, g: Y => Boolean): Option[Y] = ???
I can do it with xs.map(f).find(g)
but I don't want to traverse the whole list xs
. I don't want to use streams either. How would you suggest implement findY
?
Upvotes: 1
Views: 170
Reputation: 5768
Another possibility would be to use collectFirst
, which also returns an Option
.
xs.collectFirst{case x if g(f(x)) => f(x)}
The only downside is that you evaluate f(x)
twice if you find something that matches.
I'm not sure if it is somehow possible to bind the result f(x)
to some variable.
Upvotes: 1
Reputation: 12998
Instead of
xs.map(f).find(g)
just turn it around
xs.find(x => g(f(x)))
In both cases Option[X]
is returned.
If you want Option[Y]
, a recursive method would do the job:
@tailrec
def findFirst[X, Y](xs: List[X], f: X => Y, g: Y => Boolean): Option[Y] = {
xs match {
case Nil =>
None
case h :: t =>
val y = f(h)
if (g(y)) {
Some(y)
} else {
findFirst(t, f, g)
}
}
}
Upvotes: 1