对于/如果状态以一种方式工作,而不是另一种方式

时间:2018-02-05 13:18:48

标签: python-3.x conditional string-comparison with-statement

我通常讨厌寻求帮助,但我已经在这方面打败了自己。

当我执行以下操作时,该功能可以工作并提供所需的输出(文件之间的匹配行)。如果我反转for / if语句正在使用的文件,我不会得到文件之间匹配的行。因此,它从一个文件中拉出所需的(相同)文本,而不是另一个文件。

使用:

 with open('textfile1.txt','r') as t1, open('textfile2.txt', 'r') as t2:
     for line in t1:
         if line in t2:
             print(line)

不起作用:

 with open('textfile1.txt','r') as t1, open('textfile2.txt', 'r') as t2:
      for line in t2:
         if line in t1:
            print(line)

我确信这很简单,但我确实盯着这看的时间比我想说的还要长。这是一小段代码,我试图为我正在开展的更大项目工作。我似乎无法解决这个具体问题。

解决方案

 with open('textfile1.txt','r') as t1, open('textfile2.txt', 'r') as t2:
      t1_lines = set(t1)  
      for line in t2:
         if line in t1_lines:
            print(line)

2 个答案:

答案 0 :(得分:4)

您无法在文件中使用in并使其工作两次。

in 向前移动文件阅读器位置会发生什么。文件对象是 iterable in在这样的对象上获取每个对象(在这种情况下来自文件的行)来测试一个是否相等。找到相等的对象时,迭代停止并返回True。如果没有找到相同的对象,迭代将继续,直到你到达终点。

例如,如果t2只包含一个额外的行,那么尝试在t1中找到该行会导致所有t1被读取到试着找到它。从t2读取的任何后续行现在都将失败,因为t1已到达结尾,并且不会再返回任何行。

在这个过程中,任何时候迭代都不会被重绕。一开始。文件读指针只向前移动,永远不会回到开始。

如果在一个方案中使用in,则表示从t1读取的每一行也恰好以t2中的相同顺序出现 。如果t2包含在第一个文件中以不同顺序出现的额外行,则反之亦然。

如果您的文件较小,请将其中一个文件转到设置对象

with open('textfile1.txt','r') as t1, open('textfile2.txt', 'r') as t2:
    t1_lines = set(t1)
    for line in t2:
         if line in t1_lines:
             print(line)

一个集合允许您在常量时间中测试对象的存在;无论t1中有多少行,平均而言,它总是花费相同的时间来测试其中一行。

如果使用 large 文件,则可以使用fileobj.seek(0)强制文件指针返回到开头。但是,跨文件读取(扫描in测试时,每行都会到达)将。您可以使用memory mapping来缓解此问题,但您可能希望确保对文件行进行排序,然后使用索引或二分法来加快查找匹配行的过程。

答案 1 :(得分:3)

一次传球后迭代器已经筋疲力尽了。 t1t2是迭代器。它们在每次迭代时产生一行文件。

if line in t2遍历t2,直到找到匹配项。如果未找到匹配项,则t2将完全耗尽。因此,下次if line in t2测试时,即使line位于textfile2.txt,也不会找到匹配项。

例如,假设textfile1.txt包含

BAR
BAZ

textfile2.txt包含

FOO
BAR 

然后考虑

with open('textfile1.txt','r') as t1, open('textfile2.txt', 'r') as t2:
     for line in t2:
        if line in t1:
           print(line)

在第一次循环中,line'FOO'(让我们忽略这里的行尾字符)。 if line in t1会导致t1遍历BARBAZ。由于line不等于其中任何一个,t1已用完,循环会继续下一个值。

在第二次通过时,line等于BAR。现在if line in t1测试BAR是否在空迭代器中。所以没有印刷线。

相反,运行时

with open('textfile1.txt','r') as t1, open('textfile2.txt', 'r') as t2:
    for line in t1:
        if line in t2:
            print(line)

首次通过循环时,lineBAR。现在if line in t2为True,因为t2将生成第BAR行。