【问题标题】:Python iterating through two files by line at the same timePython同时逐行遍历两个文件
【发布时间】:2014-07-25 17:10:28
【问题描述】:

我正在尝试比较两个文件中的列以查看值是否匹配,如果匹配,我想将该行的数据合并/连接在一起。我的问题是,当分别从两个文件中逐行读取时,我无法让 python 一起遍历文件并寻找匹配项。相反,它将正确遍历一个文件并多次遍历第二个文件中的同一行...

我过去遇到过这个问题,但仍然没有真正找到解决方法。我知道缩进是一个问题,因为我使用“for line in a, for line in 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

我也尝试过使用字符串格式,但这并没有什么不同。第一种方法错误地遍历 file2,第二种方法没有给我任何输出。我已经玩了很多次并尝试了各种缩进和额外的位,但我什至不知道如何尝试修复它!请帮帮我:(

【问题讨论】:

    标签: python if-statement iteration string-matching readlines


    【解决方案1】:

    使用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会更高效。

    【讨论】:

    • 感谢您的建议。当我打印motif1 和motif2 时,它们会正确地遍历每个文件中的值。但是,当我尝试将它们与下面的行进行比较时,我只得到一个我知道绝对不正确的结果。就好像它回到了只迭代第二个文件中的一行: if motif1 == motif2: print "match" 你有什么建议吗?
    • 使用izip 会(稍微)慢一些...虽然它会消耗更少的内存...
    • 您究竟是如何提取motif1motif2 的?
    • 我正在逐行读取文件,然后将它们拆分以获取每个文件的文件名列
    • 我问的一个原因是,使用您提供的代码,您无需处理换行符。 split() 会将换行符计为分隔符,因此 'foo bar\n'.split() 将返回 ('foo', 'bar', '')。如果您随后进行反向索引,您将获得'' 而不是文件名。通常,您要么积极索引并忽略该问题,要么在拆分前使用strip()
    【解决方案2】:

    我假设您使用的是 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-20
      • 2019-09-24
      • 1970-01-01
      • 1970-01-01
      • 2020-11-20
      • 2012-07-02
      • 2018-12-10
      • 1970-01-01
      相关资源
      最近更新 更多