python predicate

python - encontrar el primer elemento en una secuencia que coincida con un predicado



predicate (4)

La respuesta de JF Sebastian es muy elegante, pero requiere Python 2.6 como señaló fortran.

Para la versión de Python <2.6, esto es lo mejor que se me ocurre:

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

Alternativamente, si necesitabas una lista más tarde (la lista maneja la StopIteration) o si necesitabas algo más que el primero, pero aún no todo, puedes hacerlo con islice:

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

ACTUALIZACIÓN: aunque personalmente estoy usando una función predefinida llamada first () que captura una StopIteration y devuelve None, he aquí una posible mejora sobre el ejemplo anterior: evite usar filter / ifilter:

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

Esta pregunta ya tiene una respuesta aquí:

Pregunta estúpida por delante: quiero una forma idiomática de encontrar el primer elemento en una lista que coincida con un predicado.

El código actual es bastante feo:

[x for x in seq if predicate(x)][0]

He pensado en cambiarlo a:

from itertools import dropwhile dropwhile(lambda x: not predicate(x), seq).next()

Pero debe haber algo más elegante ... Y sería bueno si devuelve un valor None lugar de generar una excepción si no se encuentra una coincidencia.

Sé que podría definir una función como:

def get_first(predicate, seq): for i in seq: if predicate(i): return i return None

Pero es bastante insípido comenzar a llenar el código con funciones de utilidad como esta (y las personas probablemente no notarán que ya están allí, por lo que tienden a repetirse en el tiempo) si hay componentes integrados que ya ofrecen el mismo.


No creo que haya nada de malo con las soluciones que propusiste en tu pregunta.

En mi propio código, lo implementaría así:

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

La sintaxis con () crea un generador, que es más eficiente que generar toda la lista a la vez con [] .


Podría usar una expresión de generador con un valor predeterminado y luego, a next :

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

Aunque para este one-liner necesitas usar Python> = 2.6.

Este artículo bastante popular discute aún más este problema: ¿la función de encontrar en la lista más limpia de Python? .


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

StopIteration si no hay ninguno.

next(ifilter(predicate, seq), None)

devuelve None si no hay tal elemento.