2009-04-18 4 views
15

Mis aventuras en Python continúan y mis libros favoritos vuelven a estar en silencio. Python ofrece una manera integrada para probar si una variable está dentro de un objeto iterable, utilizando el 'en' palabra clave:python, palabra clave "a en b", ¿qué hay de las múltiples a?

if "a" in "abrakadabra" : 
    print "it is definitely here" 

Pero, ¿es posible probar si más de un elemento está en la lista (cualquiera)? Actualmente, estoy usando la siguiente sintaxis, pero es un poco larga:

if "// @in " in sTxt or "// @out " in sTxt or "// @ret " in sTxt or <10 more> 
    print "found." 

de expresiones regulares curso puede ayudar, pero el uso de expresiones regulares tendrá un montón de verbosa de código y a no ser tan clara como "una en b ". ¿Hay alguna otra forma de Pitonismo?

Respuesta

45
alternatives = ("// @in ", "// @out ", "// @ret ") 
if any(a in sTxT for a in alternatives): 
    print "found" 

if all(a in sTxT for a in alternatives): 
    print "found all" 

any()all() y toma un iterable y comprueba si cualquiera/todos ellos se evalúan como un valor verdadero. Combine eso con expresiones de un generador, y puede verificar múltiples elementos.

+5

Agregué enlaces a la documentación para que S.Lott no lo menosprecie;) Sin embargo, con toda seriedad, se recomienda vincular a los documentos, espero que no le importe. –

+0

No, en absoluto. Gracias. –

7

any(snippet in text_body for snippet in ("hi", "foo", "bar", "spam"))

0

No hay forma integrada en la sintaxis para hacerlo. Sin embargo, puede usar la función 'cualquiera' para hacerlo más fácil como lo demostraron @MizardX y @Benjamin Peterson.

1

Si desea cualquier cheque a continuación, puede utilizar esta:

inthere = False 
checks = ('a', 'b') 

for check in checks: 
    if check in 'abrakadabra': 
     inthere = True 
     break 

Si desea toda la salida se podría utilizar esto:

inthere = True 
checks = ('a', 'b') 

for check in checks: 
    if check not in 'abrakadabra': 
     inthere = False 
     break 

EDIT: no sabía el más pitónico any(). Probablemente sea mejor usar eso en Python.

EDIT2: Se agregaron declaraciones de interrupción y se corrigió el todos -case.

1

También es posible usar set methods and operators:

not alternatives.isdisjoint(sTxt) # for "any" 
(alternatives & sTxt) != set() # Again, the intersection is nonempty 
alternatives <= sTxt # for "all" 

Creo que estos son más fáciles de leer que el uso de la una o todas, sino que tienen que convertir sus colecciones en conjuntos. Como la intersección y la contención son lo que más te importa, podrías considerar crearlos en primer lugar.

+0

No funciona si sTxt es una cadena. –

+0

Mi respuesta menciona que estos objetos tienen que ser conjuntos. – allyourcode

6

Si está probando muchas líneas para las mismas palabras, puede ser más rápido compilarlas como una expresión regular. por ejemplo:

import re 
words = ["// @in ", "// @out ", "// @ret "] + ["// @test%s " % i for i in range(10)] 

my_regex = re.compile("|".join(map(re.escape, words))) 

for line in lines_to_search: 
    if my_regex.search(line): print "Found match" 

Algunos sincronización rápida muestra que esto es generalmente más rápido que el enfoque any(word in theString for word in words). He probado ambos enfoques con texto variable (corto/largo con/sin coincidencias). Aquí están los resultados:

  { No keywords } | {contain Keywords } 
     short long  short long 
regex : 0.214 27.214  0.147 0.149 
any in : 0.579 81.341  0.295 0.300 

Si el rendimiento no importa sin embargo, el enfoque any() es más fácil de leer.

+0

\ o/¡Es bueno tener puntos de referencia con un reclamo "puede ser más rápido para ..."! – dbr

Cuestiones relacionadas