【问题标题】:Reading two lines at a time from two different files in Python从 Python 中的两个不同文件一次读取两行
【发布时间】:2012-12-31 10:43:07
【问题描述】:

我有两个文件如下图:

文件 1(制表符分隔):

A1 一些信息1 一些信息2 一些信息3 A1 一些信息1 一些信息2 一些信息3 B1 一些信息1 一些信息2 一些信息3 B1 一些信息1 一些信息2 一些信息3

文件 2(制表符分隔):

A1 新信息1 新信息2 新信息3 A1 新信息1 新信息2 新信息3 B1 新信息1 新信息2 新信息3 B1 新信息1 新信息2 新信息3

我想从文件 1 中一起读取两行(以 A1 和 A1 开头的行)和从文件 2 中读取两行(以 A1 和 A1 开头的行)。为了更清楚,我有两个要求:

1)从同一个文件中读取两行 2)从另一个文件中读取相同的两行。

确切地说,我想一起读取四行(两个文件中的 2 行连续的行(每个文件中的 2 行))。

我在网上搜索并获得了一个代码,可以同时读取两行,但只能从一个文件中读取。

使用 open(File1) 作为 file1: 对于 itertools.izip_longest(*[file1]*2) 中的 line1、line2:

此外,我还能够从两个文件中的每一个中读取一行:

对于枚举(itertools.izip(f1,f2))中的 i,(line1,line2): 打印第 1 行、第 2 行

但我想做这样的事情:

伪代码:

对于 file1 中的 line1、line2 和 file2 中的 line_1 和 line_2: 比较 line1 和 line2 比较 line1 和 line_1 比较 line2 和 line_1 比较 line2 和 line_2

我希望解决方案是线性时间的。所有文件都具有相同的行数,并且文件中的连续行的第一列(主 id)相同,另一个文件遵循相同的顺序(参见上面的示例)。

谢谢。

【问题讨论】:

  • 为什么compare line1 with line2 而不是compare line1 with line_2 就像line2 一样?

标签: python


【解决方案1】:

这个怎么样:

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

【讨论】:

  • 最好使用next(A)等。作为奖励,相同的代码将适用于Python3
  • 谢谢帕维尔。我尝试了您的代码,它对我来说非常有效。非常感谢。
【解决方案2】:

让我们看看如何将它们组合在一起。第一:

with open(File1) as file1:
    for line1,line2 in itertools.izip_longest(*[file1]*2):

好吧,去掉 for 循环,你就有了一个在 file 上的一次 2 行迭代器,对吧?因此,您可以对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

接下来,模式匹配可能很酷,但是在复杂表达式中间分解的嵌套模式有点太多了。所以,让我们再次从itertools 文档中借用flatten 来分解它并取消嵌套:

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 结果。)

【讨论】:

  • @PavelAnossov:是的,我开始讨论“如何写得更易读……”
  • 感谢 Abarnert 的精彩解释。我想我现在更习惯使用 izip 功能了。
【解决方案3】:
>>> 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 元素的元组

【讨论】:

    【解决方案4】:

    这是一个概括,允许任意数量的连续行具有相同的 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-09
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      相关资源
      最近更新 更多