Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find first element in a sequence that matches a predicate

People also ask

How do you extract the first element of a list?

To extract only first element from a list, we can use sapply function and access the first element with double square brackets. For example, if we have a list called LIST that contains 5 elements each containing 20 elements then the first sub-element can be extracted by using the command sapply(LIST,"[[",1).

How do you index the first element in a list?

To access the first element (12) of a list, we can use the subscript syntax [ ] by passing an index 0 . In Python lists are zero-indexed, so the first element is available at index 0 . Similarly, we can also use the slicing syntax [:1] to get the first element of a list in Python.

What is predicate in Python?

A predicate is a function that always returns True or False by performing some condition operations in a filter method. Syntax: filter(predicate, list)


To find the first element in a sequence seq that matches a predicate:

next(x for x in seq if predicate(x))

Or simply:

Python 2:

next(itertools.ifilter(predicate, seq))

Python 3:

next(filter(predicate, seq))

These will raise a StopIteration exception if the predicate does not match for any element.


To return None if there is no such element:

next((x for x in seq if predicate(x)), None)

Or:

next(filter(predicate, seq), None)

You could use a generator expression with a default value and then next it:

next((x for x in seq if predicate(x)), None)

Although for this one-liner you need to be using Python >= 2.6.

This rather popular article further discusses this issue: Cleanest Python find-in-list function?.


I don't think there's anything wrong with either solutions you proposed in your question.

In my own code, I would implement it like this though:

(x for x in seq if predicate(x)).next()

The syntax with () creates a generator, which is more efficient than generating all the list at once with [].


J.F. Sebastian's answer is most elegant but requires python 2.6 as fortran pointed out.

For Python version < 2.6, here's the best I can come up with:

from itertools import repeat,ifilter,chain
chain(ifilter(predicate,seq),repeat(None)).next()

Alternatively if you needed a list later (list handles the StopIteration), or you needed more than just the first but still not all, you can do it with islice:

from itertools import islice,ifilter
list(islice(ifilter(predicate,seq),1))

UPDATE: Although I am personally using a predefined function called first() that catches a StopIteration and returns None, Here's a possible improvement over the above example: avoid using filter / ifilter:

from itertools import islice,chain
chain((x for x in seq if predicate(x)),repeat(None)).next()