Чтение двух строк одновременно из двух разных файлов в 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


Я надеюсь, что решение будет линейным по времени. Все файлы имеют одинаковое количество строк, и первый столбец (основной идентификатор) одинаков для последовательных строк в файле, а другой файл следует тому же порядку (см. пример выше).

Спасибо.

352   4  

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 stuff
Но ты действительно не хочешь этого делать. Во-первых, большинство людей интуитивно не читают izip_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 из itertools docs снова:

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 s, вам не пришлось бы 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

    Ничего не найдено.