我有一个包含测试数据的文本文件,如下所示:
hdr 1
hdr2
hdr3
data1
data2
data3
data1
data2
....
每行之间有一个空行。
我需要创建一个包含列表的列表
[[hdr1,hdr2,hdr3],[data1,data2,data3],[data1,data2,...]
什么是简洁的,pythonic的方式来做到这一点?
我有一个包含测试数据的文本文件,如下所示:
hdr 1
hdr2
hdr3
data1
data2
data3
data1
data2
....
每行之间有一个空行。
我需要创建一个包含列表的列表
[[hdr1,hdr2,hdr3],[data1,data2,data3],[data1,data2,...]
什么是简洁的,pythonic的方式来做到这一点?
假设您的数据总是像您的示例中那样以 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()])
这只是 Charles Menguy 解决方案的简化版本,我只是将其添加为答案,因为它很难作为评论阅读。但这是关键:
首先,使用grouper
from the itertools
recipes将文件分组为 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)]
不知道它是否是最好的解决方案或者它是多少 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)