解决这类问题的关键不是考虑“文件”,而是考虑数据。什么是文件?只是一堆线。所以你只是在问如何从一个iterable中找到所有的值,这些值也在另一个iterable中。这很简单。在with open('file1') as f1, open('file2') as f2:
matches = set(f1).intersection(f2)
set构造函数接受任何像文件一样的iterable并从中生成一个集合。在
intersection方法接受任何类似于文件的iterable,并提供self集合和该iterable中的所有元素。所以,在本例中,所有的元素都在file1的所有行集合中,以及file2所有行的iterable中。在
下面是一个例子来说明它的工作原理:
文件1:
^{pr2}$
文件2:janesmith@example.com
rowdyroddypiper@example.com
jackjohnson@example.com
marysmith@example.com
代码:>>> with open('file1') as f1, open('file2') as f2:
... matches = set(f1).intersection(f2)
>>> matches
{'marysmith@example.com\n', 'rowdyroddypiper@example.com\n'}
当然,这需要将file1的全部读入内存。如果这不可能,最有效的替代方法可能是对这两个文件进行脱机排序,然后对它们进行迭代。在
但更简单的解决方案是使用dbm(具有无意义的值)作为磁盘上的集合。Here's an implementation我一拍即合。它需要Python3.3+,在Windows上可能有问题,只处理str元素,只支持^{}加intersection的最小API;如果您需要旧版本、可移植性、不同的键类型、更好的错误处理等,则可能需要3分钟以上的时间。不管怎样:>>> import dset
>>> with open('file1') as f1, open('file2') as f2:
... matches = dset.DiskSet(f1).intersection(f2)
对于中等大小的文件,任何磁盘上的解决方案显然都会慢得多,但是当你找到一些巨大的文件时,要么无法放入内存,要么更糟的是,只能把你的整个计算机扔进交换地狱,它显然会赢。在