我有一个包含测试数据的文本文件,如下所示:
hdr 1
hdr2
hdr3
data1
data2
data3
data1
data2
....
每一行之间都有一个空行。
我需要创建一个包含
的列表列表[[hdr1,hdr2,hdr3],[data1,data2,data3],[data1,data2,...]
这样做的简洁,pythonic方法是什么?
答案 0 :(得分: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])
(灵感来自this post)
编辑:您可能需要在字段上调用strip()
,以便不包含任何额外的\ n,因此arr.append([field1.strip(),field2.strip(),field3.strip()])
答案 1 :(得分:3)
这只是Charles Menguy解决方案的简化版本,我只是将其作为答案添加,因为它很难作为评论阅读。但这是关键:
首先,使用itertools
recipes中的grouper
将文件分组为6行:
groups = grouper(6, f)
接下来,你可以通过切片来抛出所有其他行:
nonblank = [group[::2] for group in groups]
或者,通过明确过滤出空白行:
nonblank = [filter(bool, group) for group in groups]
如果您需要删除每一行,可以使用列表推导或map
。一般来说,如果我不需要lambda / partial up一个新函数,我更喜欢map
,而在这里我们不需要;它只是map(str.strip, group)
。
把它放在一起,这就是整个事情,作为一个单行(我觉得它仍然很可读):
with open('input.txt') as f:
arr = [map(str.strip, group[::2]) for group in grouper(6, f)]
答案 2 :(得分: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)