2011-07-19 11 views
11

Tengo una lista de cadenas en las que quiero filtrar las cadenas que contienen palabras clave.cómo hacer re.compile() con una lista en python

quiero hacer algo como:

fruit = re.compile('apple', 'banana', 'peach', 'plum', 'pinepple', 'kiwi'] 

así que puede entonces utilizar re.search (fruta, list_of_strings) para obtener sólo las cadenas que contienen las frutas, pero no estoy seguro de cómo utilizar una lista con re.compile. ¿Alguna sugerencia? (No estoy usando Re.compile, pero creo que las expresiones regulares serían una buena forma de hacerlo.)

Respuesta

25

Debe convertir su lista de frutas en la cadena apple|banana|peach|plum|pineapple|kiwi para que sea una expresión regular válida, el siguiente debe hacer esto para usted:

fruit_list = ['apple', 'banana', 'peach', 'plum', 'pineapple', 'kiwi'] 
fruit = re.compile('|'.join(fruit_list)) 

edición: como ridgerunner señaló en los comentarios, es probable que desee añadir límites de las palabras a la expresión regular, de lo contrario la expresión regular coincidirá con palabras como plump ya que tienen una fruta como una subcadena

fruit = re.compile(r'\b(?:%s)\b' % '|'.join(fruit_list)) 
+1

+1 Pero agregaría límites de las palabras de esta manera: 'fruta = re.compile ('\ \ b (?: '+' | '.join (fruit_list +') \\ b ')) ' – ridgerunner

+0

@ridgerunner - ¡Buen punto! De hecho, la forma en que está escrito ahora 'piña' en la cuerda siempre coincidirá con 'manzana', añadiendo límites de palabras a mi respuesta. –

+0

gracias, esto es genial! – user808545

2

Puede crear una expresión regular, que coincidirá, cuando se encuentra cualquiera de los términos:

>>> s, t = "A kiwi, please.", "Strawberry anyone?" 
>>> import re 
>>> pattern = re.compile('apple|banana|peach|plum|pineapple|kiwi', re.IGNORECASE) 
>>> pattern.search(s) 
<_sre.SRE_Match object at 0x10046d4a8> 
>>> pattern.search(t) # won't find anything 
1

Código:

fruits = ['apple', 'banana', 'peach', 'plum', 'pinepple', 'kiwi'] 
fruit_re = [re.compile(fruit) for fruit in fruits] 
fruit_test = lambda x: any([pattern.search(x) for pattern in fruit_re]) 

Ejemplo de uso:

fruits_veggies = ['this is an apple', 'this is a tomato'] 
return [fruit_test(str) for str in fruits_veggies] 

Editar: Me di cuenta de que la solución de Andrew es mejor. Se podría mejorar fruit_test con expresión regular de Andrew como

fruit_test = lambda x: andrew_re.search(x) is None 
+0

O si necesita las cadenas: return [str for str en fruits_veggies if fruit_test (str)] – GeneralBecos

6

Como desea exactas partidos, hay necesidad real de expresiones regulares imo ...

fruits = ['apple', 'cherry'] 
sentences = ['green apple', 'yellow car', 'red cherry'] 
for s in sentences: 
    if any(f in s for f in fruits): 
     print s, 'contains a fruit!' 
# green apple contains a fruit! 
# red cherry contains a fruit! 

EDIT: Si necesita acceso a las cadenas que coincidan con:

from itertools import compress 

fruits = ['apple', 'banana', 'cherry'] 
s = 'green apple and red cherry' 

list(compress(fruits, (f in s for f in fruits))) 
# ['apple', 'cherry'] 
+0

En este escenario, regex es más eficiente que hacer varias pruebas de subcadenas separadas. –

+0

@Andrew: depende de la cantidad de frutas y oraciones, y aun así estamos hablando de 2 veces en cuestión de milisegundos. – hop

+0

@hop - Estoy bastante seguro de que la expresión regular será más rápida independientemente de la cantidad de frutas u oraciones.Con la expresión regular también tiene acceso a la fruta que se combinó. –

Cuestiones relacionadas