2012-10-04 20 views
5

Ho sprecato la maggior parte della mia mattinata senza riuscire a risolvere questo semplice problema. Utilizzando pitone, voglio analizzare i file di dati che assomigliano a questo:Come posso dividere un file di testo in base ai blocchi di commento in 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 

Il codice python che voglio sarebbe analizzare l'esempio sopra in tre "blocchi", la loro memorizzazione come elementi di una lista. I singoli blocchi di codice potrebbero essere memorizzati come liste di linee, con o senza le righe di commento, qualunque sia. Un modo handraulic è quello di fare questo:

#! /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]) 

sto cercando una soluzione più generale che supporta i numeri e le lunghezze di set di dati variabili. Ho provato diverse catastrofi costruite su anelli non pitonici. Penso sia meglio non ingombrare la mia domanda con loro; questo è lavoro e non "compiti".

+0

Sarà un insieme di dati sempre essere memorizzati come una stringa? –

+0

I dati sono testo non elaborato, ma alla fine li analizzerò per renderli mobili. –

+0

Sai cosa ... Guardandolo di nuovo, penso che nell'esempio che ho dato sarebbe più facile dividerlo in base ai blocchi di spazio bianchi tra i set di dati. –

risposta

5

Usa 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

Anche questo funziona perfettamente. –

+0

data l'implementazione 'contains_data', potresti voler aprire il file con la modalità di supporto newline universale – wim

+0

@wim: ho inserito un commento. Esattamente come gestire i commenti e le linee vuote dipende dai file dell'OP; potrebbero esserci linee che contengono solo spazi bianchi ecc. che devono essere analizzati. –

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

Questo dovrebbe essere "per la linea in f". –

+1

Ciò non mantiene separati i set di dati. @larsmans Ci sono anche due punti mancanti nel ciclo for. –

+1

-1 non fa quello che vuole l'op, errore di sintassi, errore semantico –

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

Questo fa esattamente quello che voglio. –

+1

Felice di ascoltare. Se hai numpy lì, ti consiglio di usare 'np.loadtxt' per analizzare i tuoi float più facilmente. – 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) 

uscita:

[[['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

Anche questo funziona, anche se non penso sia elegante come le altre soluzioni. –

Problemi correlati