2012-10-04 59 views
5

Perdí la mayor parte de mi mañana al no poder resolver este simple problema. El uso de pitón, quiero analizar archivos de datos que se ven así:¿Cómo puedo dividir un archivo de texto basado en bloques de comentarios en Python?

# This is an example comment line, it starts with a '#' character. 
# There can be a variable number of comments between each data set. 
# Comments "go with" the data set that comes after them. 
# The first data set starts on the next line: 
0.0 1.0 
1.0 2.0 
2.0 3.0 
3.0 4.0 

# Data sets are followed by variable amounts of white space. 
# The second data set starts after this comment 
5.0 6.0 
6.0 7.0 


# One more data set. 
7.0 8.0 
8.0 9.0 

El código Python Quiero sería analizar el ejemplo anterior en las tres "bloques", almacenándolos como elementos de una lista. Los bloques de códigos individuales podrían almacenarse ellos mismos como listas de líneas, con o sin las líneas de comentario, lo que sea. Una forma handraulic es hacer esto:

#! /usr/bin/env python 

# Read in data, seperate into rows_alldata 
f=open("example") 
rows = f.read().split('\n') 
f.close() 

# Do you haz teh codez? 
datasets=[] 
datasets.append(rows[0:8]) 
datasets.append(rows[9:13]) 
datasets.append(rows[15:18]) 

Busco una solución más general que soporta un número variable y longitudes de conjuntos de datos. He intentado varias catástrofes creadas a partir de bucles que no son pitónicos. Creo que es mejor no complicar mi pregunta con ellos; esto es trabajo y no "tarea".

+0

Será un conjunto de datos siempre se guarda como una cadena? –

+0

Los datos son texto sin procesar, pero al final lo analizaré en carrozas. –

+0

¿Sabes qué? Al verlo nuevamente, creo que en el ejemplo que doy sería más fácil dividirlo en función de los bloques de espacios en blanco entre los conjuntos de datos. –

Respuesta

5

Uso groupby.

from itertools import groupby 

def contains_data(ln): 
    # just an example; there are smarter ways to do this 
    return ln[0] not in "#\n" 

with open("example") as f: 
    datasets = [[ln.split() for ln in group] 
       for has_data, group in groupby(f, contains_data) 
       if has_data] 
+0

Esto también funciona perfectamente. –

+0

dada su implementación de 'contains_data', es posible que desee abrir el archivo con el modo de soporte de nueva línea universal – wim

+0

@wim: He puesto un comentario. Exactamente cómo manejar los comentarios y las líneas vacías depende de los archivos de OP; puede haber líneas que contengan solo espacios en blanco, etc., que también deben ser analizados. –

-1
datasets = [] 
with open('example') as f: 
    for line in f: 
     if line and not line.startswith('#'): 
      datasets.append(line.split()) 
+0

Eso debería ser 'para la línea en f'. –

+1

Esto no mantiene separados los conjuntos de datos. @larsmans También faltan dos puntos en el ciclo for. –

+1

-1 no hace lo que quiere el operador, error de sintaxis, error semántico –

3
datasets = [[]] 
with open('/tmp/spam.txt') as f: 
    for line in f: 
    if line.startswith('#'): 
     if datasets[-1] != []: 
     # we are in a new block 
     datasets.append([]) 
    else: 
     stripped_line = line.strip() 
     if stripped_line: 
     datasets[-1].append(stripped_line) 
+0

Esto hace exactamente lo que quiero. –

+1

Me alegra oír. Si tienes numpy allí, te recomiendo buscar usando 'np.loadtxt' para analizar tus carrozas más fácilmente. – wim

1
import pprint 

with open("test.txt") as fh: 
    codes = [] 
    codeblock = [] 

    for line in fh: 
     stripped_line = line.strip() 

     if not stripped_line: 
      continue 

     if stripped_line.startswith("#"): 
      if codeblock: 
       codes.append(codeblock) 
       codeblock = [] 

     else: 
      codeblock.append(stripped_line.split(" ")) 

    if codeblock: 
     codes.append(codeblock) 

pprint.pprint(codes) 

Salida:

[[['0.0', '1.0'], ['1.0', '2.0'], ['2.0', '3.0'], ['3.0', '4.0']], 
[['5.0', '6.0'], ['6.0', '7.0']], 
[['7.0', '8.0'], ['8.0', '9.0']]] 
+0

Esto también funciona, aunque no creo que sea tan elegante como las otras soluciones. –

Cuestiones relacionadas