2012-10-04 17 views
5

Sabahlarımın çoğunu bu basit problemi çözemedim. piton kullanarak, şuna benzer veri dosyalarını ayrıştırmak istiyorum:Python'daki yorum bloklarına dayanarak bir metin dosyasını nasıl bölebilirim?

# 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 

Bir listenin elemanları olarak saklayarak, üç "bloklar" içine yukarıdaki örneği ayrıştırmak istemeyiz piton kodu. Tek tek kod blokları, her ne olursa olsun, yorum satırları olsun veya olmasın, satır listeleri olarak saklanabilir. Bir handraulic yolu bu yapmaktır: Ben değişken numaraları ve veri setlerinin uzunluklarını destekleyen daha genel bir çözüm arıyorum

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

. Pythonic olmayan görünümlü döngülerden yapılmış birkaç felaketi denedim. Sanırım sorumu bunlarla karıştırmamak; Bu iş ve "ödev" değil.

+0

daima ayarlanmış bir veri dize olarak saklanabilir mi? –

+0

Veriler ham metin, ancak sonunda onu yüzer olarak ayrıştıracağım. –

+0

Biliyor musun ... Tekrar baktığımda, verdiğim örnekte veri kümeleri arasındaki beyaz boşluk bloklarına dayanarak onu bölmenin en kolay olacağını düşünüyorum. –

cevap

5

kullanın 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

Bu da mükemmel çalışır. –

+0

, 'includes_data' uygulamanızın verileceği, dosyayı evrensel newline destek modu – wim

+0

@ wim ile açmak isteyebilirsiniz: @ Yorum yazdım. Yorumların ve boş satırların tam olarak nasıl işleneceği, OP'nin dosyalarına bağlıdır; Ayrıca, ayrıştırılması gereken sadece beyaz boşlukları içeren çizgiler olabilir. –

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

Bu, f 'satırında olmalıdır. –

+1

Bu, veri kümelerini ayrı tutmaz. @larsmans Ayrıca, döngüde eksik bir kolon da var. –

+1

-1, op istediği ne yapmaz, sözdizimi hatası, anlam hatası –

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

Bu tam olarak istediğim şeyi yapıyor. –

+1

Duyduğuma sevindim. Orada uyuşmazsanız, floatlarınızı daha kolay ayrıştırmak için 'np.loadtxt' kullanmayı düşünmenizi öneririm. – 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) 

Çıktı:

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

Bu ayrıca çalışır, ancak diğer çözümler kadar şık olduğunu düşünmüyorum. –

İlgili konular