2012-06-19 21 views
5

Soy bastante nuevo en Python y estoy tratando de analizar un archivo. Solo ciertas líneas del archivo contienen datos de interés, y quiero terminar con un diccionario de las cosas analizadas a partir de líneas válidas coincidentes en el archivo.Cree un diccionario a partir de las coincidencias de expresiones regulares exitosas en python

El siguiente código funciona, pero es un poco feo y estoy tratando de aprender cómo se debe hacer, tal vez con una comprensión, o con una expresión regular multilínea. Estoy usando Python 3.2.

file_data = open('x:\\path\\to\\file','r').readlines() 
my_list = [] 
for line in file_data: 
    # discard lines which don't match at all 
    if re.search(pattern, line): 
     # icky, repeating search!! 
     one_tuple = re.search(pattern, line).group(3,2) 
     my_list.append(one_tuple) 
my_dict = dict(my_list) 

¿Puede sugerir una mejor implementación?

+2

Las comprensiones pueden ser bonitas, pero no se puede vincular fácilmente una variable a un valor dentro de ellas, por lo que necesitaría el doble 're.search'. Solo usa un bucle. –

Respuesta

4

Gracias por las respuestas. Después de ponerlos juntos obtuve

file_data = open('x:\\path\\to\\file','r').read() 
my_list = re.findall(pattern, file_data, re.MULTILINE) 
my_dict = {c:b for a,b,c in my_list} 

pero no creo que hubiera podido llegar hoy sin la ayuda.

+2

Es posible que desee hacer que el primer grupo en usted regex no capture ('?:') Para omitir el paso de comprensión: 'my_dict = dict (re.findall ...)' – georg

+0

Muy buena mejora. Sin embargo, leer todos los datos en una variable, en lugar de iterar sobre un objeto de archivo (y llamar implícitamente al método 'readline()'), no es muy escalable. 're.findall()' funciona perfectamente en un iterador en lugar de en una variable. – smci

4

Aquí hay algunas optimizaciones quick'n'dirty a su código:

my_dict = dict() 

with open(r'x:\path\to\file', 'r') as data: 
    for line in data: 
     match = re.search(pattern, line) 
     if match: 
      one_tuple = match.group(3, 2) 
      my_dict[one_tuple[0]] = one_tuple[1] 
+0

Gracias, eso ayudó a – WiringHarness

1

No estoy seguro de que lo recomiendo, pero aquí está una manera que usted podría intentar usar una comprensión lugar (sustituí una cadena para el archivo por simplicidad)

>>> import re 
>>> data = """1foo bar 
... 2bing baz 
... 3spam eggs 
... nomatch 
... """ 
>>> pattern = r"(.)(\w+)\s(\w+)" 
>>> {x[0]: x[1] for x in (m.group(3, 2) for m in (re.search(pattern, line) for line in data.splitlines()) if m)} 
{'baz': 'bing', 'eggs': 'spam', 'bar': 'foo'} 
+0

Dict comprensión; ¡Me gusta! – WiringHarness

2

En el espíritu de EAFP te sugiero

with open(r'x:\path\to\file', 'r') as data: 
    for line in data: 
     try: 
      m = re.search(pattern, line) 
      my_dict[m.group(2)] = m.group(3) 
     except AttributeError: 
      pass 

Otra forma es seguir usando listas, pero rediseñar el patrón para que contenga solo dos grupos (key, value). Entonces usted podría simplemente hacer:

matches = [re.findall(pattern, line) for line in data] 
    mydict = dict(x[0] for x in matches if x) 
+0

findall es útil. – WiringHarness

1
matchRes = pattern.match(line) 
if matchRes: 
    my_dict = matchRes.groupdict() 
+0

Por favor, siga el fragmento de código con algunos detalles, las explicaciones serán más claras para los lectores. –

Cuestiones relacionadas