2012-10-04 31 views
5

Tôi lãng phí hầu hết buổi sáng của mình không giải quyết vấn đề đơn giản này. Sử dụng python, tôi muốn phân tích tập tin dữ liệu mà trông như thế này:Làm cách nào để tách tệp văn bản dựa trên các khối nhận xét bằng 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 

Mã python Tôi muốn sẽ phân tích ví dụ trên thành ba "khối", lưu trữ chúng như các yếu tố của một danh sách. Các khối mã riêng lẻ có thể được lưu trữ dưới dạng danh sách các dòng, có hoặc không có dòng chú thích, bất cứ điều gì. Một cách handraulic là để làm điều này:

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

Tôi đang tìm một giải pháp tổng quát hơn hỗ trợ số lượng và độ dài của tập hợp dữ liệu. Tôi đã thử một số thảm họa được xây dựng từ các vòng tìm kiếm không phải pythonic. Tôi nghĩ tốt nhất là không làm xáo trộn câu hỏi của tôi với họ; đây là công việc chứ không phải "bài tập về nhà".

+0

sẽ một tập dữ liệu luôn được lưu trữ như là một chuỗi? –

+0

Dữ liệu là văn bản thô, nhưng cuối cùng tôi sẽ phân tích nó thành phao. –

+0

Bạn biết không ... Nhìn vào nó một lần nữa, tôi nghĩ rằng trong ví dụ tôi cho nó sẽ là dễ nhất để chia nó dựa trên các khối không gian màu trắng giữa các tập dữ liệu. –

Trả lời

5

Sử dụng 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

Điều này cũng hoạt động hoàn hảo. –

+0

cho việc triển khai 'contains_data' của bạn, bạn có thể muốn mở tệp với chế độ hỗ trợ dòng mới phổ quát – wim

+0

@wim: Tôi đã đưa vào nhận xét. Chính xác cách xử lý các chú thích và các dòng trống phụ thuộc vào các tệp của OP; có thể có các dòng chỉ chứa khoảng trống, v.v. mà cũng phải được phân tích cú pháp. –

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

Điều đó phải là 'cho dòng trong f'. –

+1

Điều này không giữ riêng bộ dữ liệu. @ larsmans Còn có một dấu hai chấm bị thiếu trong vòng lặp for. –

+1

-1 doesnt làm những gì op muốn, lỗi cú pháp, lỗi ngữ nghĩa –

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

Điều này thực hiện chính xác những gì tôi muốn. –

+1

Rất vui khi được nghe. Nếu bạn có numpy ở đó, tôi khuyên bạn nên xem xét sử dụng 'np.loadtxt' để phân tích các float của bạn dễ dàng hơn. – 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) 

Output:

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

Điều này cũng hoạt động, mặc dù tôi không nghĩ nó thanh lịch như các giải pháp khác. –

Các vấn đề liên quan