我通常讨厌寻求帮助,但我已经在这方面打败了自己。
当我执行以下操作时,该功能可以工作并提供所需的输出(文件之间的匹配行)。如果我反转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)
答案 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)
一次传球后迭代器已经筋疲力尽了。 t1
和t2
是迭代器。它们在每次迭代时产生一行文件。
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
遍历BAR
和BAZ
。由于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)
首次通过循环时,line
为BAR
。现在if line in t2
为True,因为t2
将生成第BAR
行。