Python перебирает два файла построчно одновременно

Я пытаюсь сравнить столбцы в двух файлах, чтобы увидеть, совпадают ли значения, и если есть совпадение, я хочу объединить/объединить данные для этой строки вместе. Моя проблема в том, что при чтении строки за строкой из двух файлов по отдельности я не могу заставить python перебирать файлы вместе и искать совпадение. Вместо этого он будет правильно перебирать один файл и повторять одну и ту же строку во втором файле несколько раз...

У меня была эта проблема в прошлом, и я до сих пор не нашел способа ее обойти. Я знаю, что отступы - это одна из проблем, так как я возился с циклом, используя «для строки в a, для строки в b», поэтому я думал, что то, что я пробовал ниже, сработает, но это не так. Я искал решения, но, похоже, никто не использует тот же метод, поэтому я задаюсь вопросом, полностью ли я не в курсе, как это сделать? Может ли кто-нибудь объяснить, как лучше это сделать, и будет ли мой метод работать вообще, а если нет, то почему? Спасибо, это очень ценно!

Это форматы моих двух файлов, в основном я хочу сравнить имена файлов столбцов в обоих файлах, и если они совпадают, я хочу объединить строки вместе.

file1:
cluster_id  hypothesis_id   filename    M1_name_offset  Orientation
1   71133076    unique_name_1.png   esc_sox2_Sox1_80_4  forward
1   50099120    unique_name_4.png   hb_cebpb_ETS1_139_7 forward
1   91895576    unique_name_11.png  he_tal1_at_AC_acptr_258_11  forward

file2:
Name                Cluster_No  Pattern     filename
esc_sox2_Sox1_80    Cluster1    AP1(1N)ETS      unique_name_4.png
hb_cebpb_ETS1_139   Cluster1    CREB(1N)ETS     unique_name_11.png
he_tal1_at_AC_acptr_258 Cluster2    ETS(-1N)ZIC     unique_name_3.png

Что я пробовал:

for aline in file1:
    motif1 = aline.split()[2]
    for bline in file2:
        motif2 = bline.split()[-1]
            if motif1 = motif2:
                print "match", aline, bline

Я также пробовал:

for aline in file1:
    motif1 = aline.split()[2]
for bline in file2:
    motif2 = bline.split()[-1]
        if motif1 = motif2:
            print "match", aline, bline

Я также пытался использовать форматирование строк, но это не имело значения. Первый способ неправильно перебирает файл2, а второй способ не дает мне никакого вывода. Я много играл с этим и пробовал различные углубления и дополнительные биты, но я в тупике, как даже попытаться это исправить! Помогите пожалуйста мне :(


person user3078840    schedule 25.07.2014    source источник


Ответы (2)


Используйте встроенную функцию zip.

with open(file1) as f1, open(file2) as f2:
    for line1, line2 in zip(f1, f2):
        motif1 = line1.split()[0]
        motif2 = line2.split()[0]
        ...

Обратите внимание, что zip ведет себя по-разному в python2 и python3. В python2 вместо этого было бы более эффективно использовать itertools.izip.

person shx2    schedule 25.07.2014
comment
Спасибо за ваше предложение. Когда я печатаю motif1 и motif2, они правильно перебирают значения в каждом файле. Однако, когда я пытаюсь сравнить их со строками ниже, я получаю только один результат, который, как я знаю, определенно неверен. Как будто он вернулся к повторению только одной строки во втором файле: if motif1 == motif2: print match Есть ли у вас какие-либо предложения? - person user3078840; 25.07.2014
comment
было бы (незначительно) медленнее использовать izip... хотя это потребляло бы меньше памяти... - person Joran Beasley; 25.07.2014
comment
Как именно вы извлекаете motif1 и motif2? - person Peter DeGlopper; 25.07.2014
comment
Я читаю файлы построчно, а затем разбиваю их, чтобы получить столбцы с именем файла для каждого файла. - person user3078840; 25.07.2014
comment
Одна из причин, по которой я спрашиваю, заключается в том, что в представленном коде вы не имеете дело с символами новой строки. split() будет считать символы новой строки символом-разделителем, поэтому 'foo bar\n'.split() вернет ('foo', 'bar', ''). Если вы затем выполните обратное индексирование, вы получите '' вместо имени файла. Обычно вы либо ставите положительный индекс и игнорируете проблему, либо используете strip() перед разделением. - person Peter DeGlopper; 28.07.2014
comment
Или, если подумать, использовать модуль csv и позволить ему позаботиться о новых строках за вас. - person Peter DeGlopper; 28.07.2014

Я предполагаю, что вы используете Python 3. Вот хорошая абстракция, iterlines. Он скрывает сложность открытия, чтения, сопряжения и закрытия n файлов. Обратите внимание на использование zip_longest, это предотвращает молчаливое отбрасывание концов более длинных файлов.

def iterlines(*paths, fillvalue=None, **open_kwargs):
    files = []
    try:
        for path in paths:
            files.append(open(path, **open_kwargs))
        for lines in zip_longest(*files, fillvalue=fillvalue):
            yield lines
    finally:
        for file_ in files:
            with suppress():
                file_.close()

Использование

for line_a, line_b in iterlines('a.txt', 'b.txt'):
    print(line_a, line_b)

Полный код

from contextlib import suppress
from itertools import zip_longest


def iterlines(*paths, fillvalue=None, **open_kwargs):
    files = []
    try:
        for path in paths:
            files.append(open(path, **open_kwargs))
        for lines in zip_longest(*files, fillvalue=fillvalue):
            yield lines
    finally:
        for file_ in files:
            with suppress():
                file_.close()


for lines in iterlines('a.txt', 'b.txt', 'd.txt'):
    print(lines)
person Peter Sutton    schedule 25.07.2014