Possible Duplicate:
Python: find first element in a sequence that matches a predicate
Is there a higher order function in Python standard library that encapsulates the following control flow pattern?
>>> def find(pred, coll):
... for x in coll:
... if pred(x):
... return x
...
>>> find(lambda n : n % 2 == 0, [3, 5, 8, 9, 6])
8
>>> find(lambda n : n % 2 == 0, [3, 5, 7, 9, 6])
6
>>> find(lambda n : n % 2 == 0, [3, 5, 7, 9, 1])
You can combine ifilter
and islice
to get just the first matching element.
>>> list(itertools.islice(itertools.ifilter(lambda n: n % 2 == 0, lst), 1))
[8]
However, I wouldn't consider this anyhow more readable or nicer than the original code you posted. Wrapped in a function it will be much nicer though. And since next
only returns one element there is no need for islice
anymore:
def find(pred, iterable):
return next(itertools.ifilter(pred, iterable), None)
It returns None
if no element was found.
However, you still have the rather slow call of the predicate function every loop. Please consider using a list comprehension or generator expression instead:
>>> next((x for x in lst if x % 2 == 0), None)
8
itertools.ifilter()
can do this, if you just grab the first element of the resulting iterable.
itertools.ifilter(pred, col1).next()
Similarly, so could a generator object (again, taking the first item out of the resulting generator):
(i for i in col1 if i % 2 == 0).next()
Since both of these are lazy-evaluated, you'll only evaluate as much of the input iterable as is necessary to get to the first element that satisfies the predicate. Note that if nothing matches the predicate, you'll get a StopIteration
exception. You can avoid this by using the next()
builtin instead:
next((i for i in col1 if i % 2 == 0), None)
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