2

我有一个包含测试数据的文本文件,如下所示:

hdr 1

hdr2

hdr3

data1

data2

data3

data1

data2

....

每行之间有一个空行。

我需要创建一个包含列表的列表

[[hdr1,hdr2,hdr3],[data1,data2,data3],[data1,data2,...]

什么是简洁的,pythonic的方式来做到这一点?

4

3 回答 3

7

假设您的数据总是像您的示例中那样以 3 为一组,您可能会使用itertools,如果您将相同的迭代器传递 6 次,那么您最终应该得到 6 个字段,其中 3 个是空行,其他的您感兴趣的 3 人组:

import itertools

arr = []
with open('input.txt') as f:
    for field1,blank1,field2,blank2,field3,blank3 in itertools.izip_longest(*[f]*6):
        arr.append([field1,field2,field3])

(灵感来自这篇文章

编辑:您可能需要调用strip()这些字段以便不包含任何额外的\n,所以arr.append([field1.strip(),field2.strip(),field3.strip()])

于 2013-02-02T01:16:35.810 回答
3

这只是 Charles Menguy 解决方案的简化版本,我只是将其添加为答案,因为它很难作为评论阅读。但这是关键:

首先,使用grouperfrom the itertoolsrecipes将文件分组为 6 行组:

groups = grouper(6, f)

接下来,您可以通过切片来丢弃所有其他行:

nonblank = [group[::2] for group in groups]

或者,或者,通过明确过滤掉空白行:

nonblank = [filter(bool, group) for group in groups]

如果您需要剥离每一行,您可以使用列表推导,或者map. 一般来说,map如果我不需要 lambda/partial 一个新函数,我更喜欢,这里我们不需要;只是map(str.strip, group)

把它放在一起,这就是整个事情,作为一个单行(我认为它仍然很可读):

with open('input.txt') as f:
    arr = [map(str.strip, group[::2]) for group in grouper(6, f)]
于 2013-02-02T01:57:55.553 回答
0

不知道它是否是最好的解决方案或者它是多少 pythonic,但您可以简单地使用正则表达式来解析文件的行:

import re

regex = re.compile(r'^(\w+)\s*(\d+)')
last_groups = None
group = []
data = []

with open('data.txt', 'r') as f:
    for line in f:
        match = regex.search(line)
        if match:
            if last_groups is None:
                last_groups = match.groups()

            if last_groups[0] == match.groups()[0] and \
                    int(last_groups[1]) <= int(match.groups()[1]):
                last_groups = match.groups()
                group.append(''.join(last_groups))
            else:
                data.append(group)
                last_groups = match.groups()
                group = [''.join(last_groups)]

if group:
    data.append(group)
于 2013-02-02T01:45:53.020 回答