两个文件比较

Two files comparsion

我有一个非常奇怪的问题。我有三个文件,其中包含一列数字。我只需要从第一个文件中获取唯一值,这些值不存在于第二个和第三个文件中。

我试过 Python 喜欢:

for e in firstfile:
    if e not in secondfile:
        resultfile.append(e)
return resultfile

第三个文件也一样。

我在 linux shell 中尝试了 uniq、sort、diff、一些 awk 脚本和 comm,如下所示:Fast way of finding lines in one file that are not in another?

但我每次得到的唯一结果是与之前的第一个文件中相同的行数。我完全不明白!

也许,我错过了什么?也许这是一种格式?但是,我检查了很多次。以下是文件:http://dropmefiles.com/BaKGj

P.S。后来我以为根本没有唯一行,但我手动检查了一下,第一个文件中的一些数字是唯一的。

P.P.S。文件格式如下:

380500100000 
380500100001 
380500100002 
380500100003 
380500100004    
380500100005 
380500100008 
380500100020 
380500100022 
380500100050    
380500100070 
380500100080

最简单的方法是将每个文件读入 set,然后使用 Python 的(非常有效的)集合操作来进行比较。

file1 = set()
file2 = set()

for element in firstfile:
    file1.add(element)

for element in secondfile:
    file2.add(element)

unique = file1 - file2

怎么了

And same for third file

如果你真的对第三个文件做同样的事情,即将第一个文件的原始内容与第三个文件进行比较,你可以引入不在第二个文件中但在第三个文件中的项目的重复项。例如:

file 1:
1
2
3

file 2:
1

file 3:
2

处理文件 2 后,resultfile 将包含 2 和 3。然后在处理文件 3 后,resultfile 将包含 2 和 3(从第一个 运行 开始)plus 1 和 3,即 2, 3, 1, 3。但是,结果应该只是 3。

从您的代码中不清楚您是否真的在写每个 运行 和 文件 resultfile 的输出。如果是,则应将其用作第二个和后续 运行 的输入,不要再次处理第一个文件。


更好的修复方法

如果您不需要保留第一个文件中的行顺序,您可以像这样使用 set.difference()

with open('file1') as f1, open('file2') as f2, open('file3') as f3:
    unique_f1 = set(f1).difference(f2, f3)

请注意,这将包括文件中存在的所有空格(包括换行符)。如果您想忽略每一行的前导和尾随空格:

from itertools import chain

with open('file1') as f1, open('file2') as f2, open('file3') as f3:
    unique_f1 = set(map(str.strip, f1)).difference(map(str.strip, chain(f2, f3)))

以上假定 Python 3。如果您正在使用 Python 2,那么为了提高效率,可选择导入 itertools.imap 并使用它代替 map()

或者您可能希望将数据视为数字(我在这里假设 float,但您可以改用 int):

from itertools import chain

with open('file1') as f1, open('file2') as f2, open('file3') as f3:
    unique_f1 = set(map(float, f1)).difference(map(float, chain(f2, f3)))

问题可能在于 first.csv 是严格的 ASCII 文本,而 second.csvthird.csv 是 ASCII 文本,带有 CRLF 行终止符。我建议您将它们更改为相同的格式(ASCII 文本可能效果最好)。

$ file first.csv
first.csv: ASCII text 

$ file second.csv
second.csv: ASCII text, with CRLF line terminators

$ file third.csv
third.csv: ASCII text, with CRLF line terminators