Чтение двух строк одновременно из двух разных файлов в Python
У меня есть два файла, как показано ниже:
Файл 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
Я хочу прочитать две строки вместе (строки, начинающиеся с A1 и A1) из файла 1 и две строки (строки, начинающиеся с A1 и A1) из файла 2. Чтобы быть более ясным, у меня есть два требования:
1) Reading two lines from the same file
2) Read same two lines from the other file.
Чтобы быть точным, я хочу прочитать четыре строки вместе (2 последовательные строки из двух файлов (2 строки из каждого файла)).
Я искал в интернете и смог получить код для чтения двух строк вместе, но только из одного файла.
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
Но я хочу сделать sth, как:
Псевдокод:
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
Я надеюсь, что решение будет линейным по времени. Все файлы имеют одинаковое количество строк, и первый столбец (основной идентификатор) одинаков для последовательных строк в файле, а другой файл следует тому же порядку (см. пример выше).
Спасибо.
4 ответов:
Как насчет этого:
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
Давайте посмотрим, как мы можем собрать их вместе. Первый:
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 stuffizip_longest(*[file1]*2)и не понимают, что это группировка по парам. Оберните это как функцию. На самом деле, даже не пишите функцию самостоятельно; возьмитеgrouperпрямо из документации itertools .Итак, теперь это:
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изitertoolsdocs снова: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подняли паруgroupers, вам не пришлось быflattenрезультат.)
>>> 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
Вот обобщение, которое позволяет любое количество последовательных строк с одним и тем же столбцом идентификатора:
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)
Comments