我有两个文件,如下所示:
文件1(制表符分隔):
A1 someinfo1 someinfo2 someinfo3 A1 someinfo1 someinfo2 someinfo3 B1 someinfo1 someinfo2 someinfo3 B1 someinfo1 someinfo2 someinfo3
文件2(制表符分隔):
A1 newinfo1 newinfo2 newinfo3 A1 newinfo1 newinfo2 newinfo3 B1 newinfo1 newinfo2 newinfo3 B1 newinfo1 newinfo2 newinfo3
我想从文件1中读取两行(从A1和A1开始的行)和从文件2中读取两行(以A1和A1开头的行)。为了更清楚,我有两个要求:
1) Reading two lines from the same file 2) Read same two lines from the other file.
准确地说,我想一起阅读四行(两个文件中的两行连续(每个文件两行))。
我在网上搜索并且能够获得一个代码来一起读取两行,但只能从一个文件中读取。
with open(File1) as file1: for line1,line2 in itertools.izip_longest(*[file1]*2):
此外,我还能够从两个文件中读取一行:
for i,(line1,line2) in enumerate(itertools.izip(f1,f2)): print line1, line2
但我想做某事:
伪代码:
for line1, line2 from file1 and line_1 and line_2 from file2: compare line1 with line2 compare line1 with line_1 compare line2 with line_1 compare line2 with line_2
我希望解决方案是一个线性时间的解决方案。所有文件具有相同的行数,并且第一列(主要ID)对于文件中的连续行是相同的,而另一个文件遵循相同的顺序(参见上面的示例)。
感谢。
答案 0 :(得分:6)
这个怎么样:
with open('a') as A, open('b') as B:
while True:
try:
lineA1, lineA2, lineB1, lineB2 = next(A), next(A), next(B), next(B)
# compare lines
# ...
except StopIteration:
break
答案 1 :(得分:1)
让我们看看我们如何将这些结合在一起。第一:
with open(File1) as file1:
for line1,line2 in itertools.izip_longest(*[file1]*2):
好吧,取出for
循环,你有一个2行一次的迭代器而不是file
,对吗?因此,您可以对file2
执行相同的操作。然后你可以zip
他们在一起:
with open(File1) as file1, open(File2) as file2:
f1 = itertools.izip_longest(*[file1]*2)
f2 = itertools.izip_longest(*[file2]*2)
for i,((f1_line1, f1_line2), (f2_line1, f2_line2)) in enumerate(itertools.izip(f1,f2)):
# do stuff
但你真的不想这样做。
首先,大多数人并不直观地阅读izip_longest(*[file1]*2)
并意识到它是成对分组的。将其作为一种功能包装起来。事实上,甚至不要自己写这个功能;从itertools documentation开始grouper
。
现在,它是:
with open(File1) as file1, open(File2) as file2:
pairs1 = grouper(2, file1)
pairs2 = grouper(2, file2)
for i,((f1_line1, f1_line2), (f2_line1, f2_line2)) in enumerate(itertools.izip(f1,f2)):
# do stuff
接下来,模式匹配可能很酷,但是在复杂表达式中间分解的嵌套模式有点过分。所以,让我们分解它,并通过再次从flatten
文档中借用itertools
来取消嵌套:
with open(File1) as file1, open(File2) as file2:
pairs1 = grouper(2, file1)
pairs2 = grouper(2, file2)
zipped_pairs = itertools.izip(pairs1, pairs2)
for i, zipped_pair in enumerate(zipped_pairs):
f1_line1, f1_line2, f2_line1, f2_line2 = flatten(zipped_pair)
# do stuff
这个解决方案的优点是它是抽象的和通用的,这意味着如果你以后决定需要5行或3个文件的组,那么这种变化是显而易见的。
这个解决方案的缺点是它是抽象的和通用的,这意味着它不可能像做具体的等价物一样简单。 (例如,如果您没有zip
一对grouper
,则不必flatten
结果。)
答案 2 :(得分:1)
>>> from itertools import izip
>>> with open("file1") as file1, open("file2") as file2:
... for a1, a2, b1, b2 in izip(file1, file1, file2, file2):
... print a1, a2, b1, b2
...
A1 someinfo1 someinfo2 someinfo3
A1 someinfo1 someinfo2 someinfo3
A1 newinfo1 newinfo2 newinfo3
A1 newinfo1 newinfo2 newinfo3
B1 someinfo1 someinfo2 someinfo3
B1 someinfo1 someinfo2 someinfo3
B1 newinfo1 newinfo2 newinfo3
B1 newinfo1 newinfo2 newinfo3
你可以将行数设为参数(n
),如下所示
for lines in izip(*[file1]*n+[file2]*n):
现在行将是具有n*2
元素的元组
答案 3 :(得分:0)
这是一个允许任意数量的具有相同id列的连续行的概括:
from itertools import groupby, izip, product
getid = lambda line: line.partition(" ")[0] # first space-separated column
same_id = lambda lines: groupby(lines, key=getid)
with open(File1) as file1, open(File2) as file2:
for (id1, lines1), (id2, lines2) in izip(same_id(file1), same_id(file2)):
if id1 != id2:
# handle error here
break
# compare all possible combinations
for a, b in product(lines1, lines2):
compare(a, b)