Puede mejorar las cosas al crear su lista de palabras clave como una expresión regular.
Esto puede permitir que se prueben en paralelo, pero dependerá en gran medida de las palabras clave (por ejemplo, algunos trabajos pueden reutilizarse probando "hola" e "infierno", en lugar de buscar todas las frases desde el principio . para cada palabra
Usted puede hacer esto mediante la ejecución:
import re
keyword_re = re.compile("|".join(map(re.escape, keywords)))
continuación:
>>> bool(keyword_re.search('hello, world'))
True
>>> bool(keyword_re.search('hi, earth'))
False
(en realidad va a devolver un objeto partido en descubierto, y Ninguno si no se encuentra, esto podría ser útil si necesita saber qué palabra clave concuerda)
Sin embargo, la cantidad (si la suma) que obtenga dependerá de las palabras clave. Si solo tiene uno o dos, mantenga su enfoque actual. Si tiene una lista grande, puede valer la pena probar y perfilar para ver cuál funciona mejor.
[Editar] Como referencia, así es como lo hacen los enfoques para su ejemplo:
good1 good2 good3 bad1 bad2
original : 0.206 0.233 0.229 0.390 63.879
gnud (join) : 0.257 0.347 4.600 0.281 6.706
regex : 0.766 1.018 0.397 0.764 124.351
regex (join) : 0.345 0.337 3.305 0.481 48.666
Obviamente, para este caso, su enfoque lleva a cabo mucho mejor que el de expresiones regulares. Si esto siempre será así depende mucho del número y la complejidad de las palabras clave, y de los datos de entrada que se verificarán. Para números grandes de palabras clave, listas largas o frases que raramente coinciden, las expresiones regulares pueden funcionar mejor, pero haga obtenga información de tiempo, y quizás intente incluso optimizaciones más simples (como mover las palabras más comunes al principio de su lista de palabras clave) primero. A veces, el enfoque más simple es el mejor.
[Edit2] Se actualizó la tabla con gnud's solution, y un enfoque similar antes de aplicar los regexes. También agregué 2 nuevas pruebas:
good_data3 = good_data2 * 500 # 1000 items, the first of which matches.
bad_data2 = bad_data * 500 # 1000 items, none of which matches.
que muestran las diversas fortalezas y debilidades.Unirse es peor cuando se encuentra una coincidencia (ya que siempre hay un costo inicial pagado para unirse a la lista; este es el mejor caso posible para el método de búsqueda lineal); sin embargo, para las listas que no coinciden, se realiza mejor. Mucho mejor cuando hay una gran cantidad de artículos en el list.case).
Buena solución, estaba pensando exactamente en eso. Debería ser bastante rápido en comparación con las expresiones regulares, ya que la verificación __contains__ se realiza con un Boyer-Moore modificado y, por lo tanto, debería omitir muy bien los caracteres separadores. –
Buena idea, y tiene un efecto * muy * significativo en listas grandes, probablemente como dijo Torsten porque python puede reutilizar las tablas de búsqueda que crea en lugar de tirarlas y recrearlas para cada elemento de la lista. Actualizaré mis cifras de tiempo. – Brian
¡Unirse a la matriz es una gran idea! Decidí usar esto en combo con la sugerencia de S.Lott sobre la función any(). ¡Gracias! –