2011-05-18 23 views
16

¿Cómo puedo encontrar un objeto en una secuencia que satisfaga un criterio particular? Comprensión de lista y filtro revisa toda la lista. ¿La única alternativa es un lazo hecho a mano?python sequence find function

mylist = [10, 2, 20, 5, 50] 
find(mylist, lambda x:x>10) # returns 20 
+0

Te refieres solo quieres encontrar el primer objeto que coincida con los criterios? – Blair

+0

para más de un objeto que debe hacer '[i for i in mylist if i> 10]' – JBernardo

+0

@Blair y @JBernardo, sí, solo el primer objeto coincidente. – Salil

Respuesta

22

aquí es el patrón de uso:

mylist = [10, 2, 20, 5, 50] 
found = next(i for i in mylist if predicate(i)) 

O, en Python 2.4/2.5 y, next() es un no es un orden interna:

found = (i for i in mylist if predicate(i)).next() 

tenga en cuenta que next() plantea StopIteration si ningún elemento era encontró. En la mayoría de los casos, probablemente sea bueno, usted pidió el primer elemento, no existe ese elemento, por lo que el programa probablemente no pueda continuar.

Si, por el contrario, se hace saben qué hacer en ese caso, se puede suministrar un valor predeterminado al next():

conf_files = ['~/.foorc', '/etc/foorc'] 
conf_file = next((f for f in conf_files if os.path.exists(f)), 
       '/usr/lib/share/foo.defaults') 
+0

¿Lo ha sacado usted mismo o lo ha visto en alguna parte y, de ser así, dónde? Además, ¿no sería mejor utilizar 'next' incorporado y pasar el valor predeterminado (probablemente en este caso la lista está vacía)? –

+1

'next()' ya se introdujo en Python 2.6 - http://docs.python.org/2.6/library/functions.html?highlight=next#next –

+0

@Piotr: creo que eso puede depender del caso de uso particular . Si desea el primer elemento de una secuencia vacía, no hay un valor correcto para devolver, no tiene un primer elemento. Puede tener un buen sentido hacer una excepción. 'bool (foo (next (filter (foo, []), []))! = True', es decir, a menos que' foo' sea algo así como 'lambda x: x == []', y '[]' ciertamente no es * in * '[]', por lo que es una mentira en cualquier caso. – SingleNegationElimination

5

Si sólo desea que el primer mayor de 10 puede utilizar itertools.ifilter:

import itertools 
first_gt10 = itertools.ifilter(lambda x: x>10, [10, 2, 20, 5, 50]).next() 

Si desea que todos los mayores de 10, puede ser sencilla de utilizar un list-comprehension:

all_gt10 = [i for i in mylist if i > 10] 
7

En realidad, en Python 3, al menos, el filtro no pasa por la lista completa.

comprobar:

def test_it(x): 
    print(x) 
    return x>10 

var = next(filter(test_it, range(20))) 

En Python 3.2, que imprime 0-11, y asigna var a 11.

En versiones 2.x de Python que puede necesitar utilizar itertools. ifilter.

+0

Buena llamada; 'zip',' map', y 'filter' se vuelven flojos en Python3. (Reemplazos para 'imap',' izip' y 'ifilter' de Python2.) – bernie

0

demasiado vago para escribir:

mylist = [10, 2, 20, 5, 50] 
max(mylist, key=lambda x: x>10)