簡體   English   中英

如何在Python中讀取具有可變多行數據的文件

[英]How to read a file with variable multi-row data in Python

我有一個大約100Mb的文件,看起來像這樣:

#meta data 1    
skadjflaskdjfasljdfalskdjfl
sdkfjhasdlkgjhsdlkjghlaskdj
asdhfk
#meta data 2
jflaksdjflaksjdflkjasdlfjas
ldaksjflkdsajlkdfj
#meta data 3
alsdkjflasdjkfglalaskdjf

該文件包含一行元數據,它對應於幾個僅包含字母數字字符的可變長度數據。 將此數據讀入如下所示的簡單列表的最佳方法是什么:

data = [[#meta data 1, skadjflaskdjfasljdfalskdjflsdkfjhasdlkgjhsdlkjghlaskdjasdhfk],
       [#meta data 2, jflaksdjflaksjdflkjasdlfjasldaksjflkdsajlkdfj],
       [#meta data 3, alsdkjflasdjkfglalaskdjf]]

我最初的想法是使用read()方法將整個文件讀入內存,然后使用正則表達式將數據解析為所需的格式。 有沒有更好的pythonic方式? 所有元數據行均以八索角開頭,所有數據行均為字母數字。 謝謝!

itertools.groupby提供了一種簡單的方法來將行收集到組中:

import itertools

data=[]
with open('data.txt','r') as f:
    for key,group in itertools.groupby(f,lambda line: line.startswith('#meta')):
        if key:
            meta=next(group).strip()
        else:
            lines=''.join(group).strip()
            data.append((meta,lines))
print(data)            

產量

[('#meta data 1', 'skadjflaskdjfasljdfalskdjfl\nsdkfjhasdlkgjhsdlkjghlaskdj\nasdhfk'), ('#meta data 2', 'jflaksdjflaksjdflkjasdlfjas\nldaksjflkdsajlkdfj'), ('#meta data 3', 'alsdkjflasdjkfglalaskdjf')]

表達方式

itertools.groupby(f,lambda line: line.startswith('#meta'))

返回一個迭代器。 它循環遍歷f的行,並在每行上調用lambda函數。 當遇到以#meta開頭的#meta ,該函數返回True ,否則返回False

itertools.groupby收集所有返回相同值的連續行。

因此,將以#meta開頭的行放置在其自己的組中,然后將所有非以#meta開頭的后續行放置在下一組中,依此類推。

keylambda函數的返回值。 在這種情況下,它將為TrueFalse

我不知道這是否是最快的方法,但是從我的頭開始:

data = []
with open('input.file', 'r') as fp:
    for line in fp:
        line = line.strip()
        if line[0] == '#':
            data.append((line, []))
        else:
            data[-1][1].append(line)
data = [(X, ''.join(Y)) for X, Y in data]

我猜是這樣的:

result = []
for line in file.readlines():
    if line[0] == '#':
        result.append([line])
    else:
        if len(result[-1]) == 1:
            result[-1].append(line)
        else:
            result[-1][-1] += line

未經測試。

我會保持簡單,例如:

data = [] # result
lastmeta = None # the last metadata line seen
chunks = [] # lines since the last metadata line
for line in input:
    if line[0] == '#': # metadata
        if lastmeta: # need to flush data we've collected
            data.append((lastmeta, ''.join(chunks))
        lastmeta = line
    else:
        chunks.append(line)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM