高效、准确地压缩和比较Python列表的方法?

高效、准确地压缩和比较Python列表的方法?,python,list,comparison,hash,Python,List,Comparison,Hash,我正在尝试在两个CSV文件中的各行之间进行某种复杂的区分。我需要确保一个文件中的一行不会出现在另一个文件中,但我不能保证这两个文件中的行的顺序。作为起点,我一直在尝试比较行的字符串表示形式(即Python列表)的散列。例如: import csv hashes = [] for row in csv.reader(open('old.csv','rb')): hashes.append( hash(str(row)) ) for row in csv.reader(open('new.c

我正在尝试在两个CSV文件中的各行之间进行某种复杂的区分。我需要确保一个文件中的一行不会出现在另一个文件中,但我不能保证这两个文件中的行的顺序。作为起点,我一直在尝试比较行的字符串表示形式(即Python列表)的散列。例如:

import csv

hashes = []
for row in csv.reader(open('old.csv','rb')):
  hashes.append( hash(str(row)) )

for row in csv.reader(open('new.csv','rb')):
  if hash(str(row)) not in hashes:
    print 'Not found'
但这是惨败的。我受到人为施加的无法更改的内存限制的限制,因此我使用哈希,而不是直接存储和比较列表。我正在比较的一些文件的大小可以是数百兆字节。有没有办法准确地压缩Python列表,这样就可以在简单的平等性方面与其他列表进行比较?也就是说,一个实际工作的哈希系统?加分:为什么上面的方法不起作用

编辑:

谢谢你的建议!让我澄清一些事情。“悲惨的失败”意味着在被
CSV.reader
对象读入后,具有完全相同数据的两行在调用列表对象上的
str
后没有散列到相同的值。我将尝试下面的一些建议。我也无法对原始文件进行哈希,因为下面两行包含相同的数据,但行中的字符不同:

1, 2.3, David S, Monday
1, 2.3, "David S", Monday
我也已经在做一些事情,如字符串剥离,以使数据更加统一,但似乎没有用。我不是在寻找一种非常智能的差异逻辑,即
0
0.0
相同

编辑2:


问题解决了。基本上起作用的是,我需要更多的预格式化,比如转换整数和浮点,等等,我需要更改我的哈希函数。这两个变化似乎都对我起到了作用。

需要更多关于“惨败”到底意味着什么的信息。如果你只是没有得到两者之间的正确比较,也许可以解决这个问题

我以前在使用内置哈希库时遇到过麻烦,并用它解决了问题


编辑:正如有人在另一篇文章中建议的那样,问题可能在于假设两个文件要求每一行完全相同。在计算哈希之前,您可能希望尝试解析csv字段并将其附加到具有相同格式的字符串(可能是修剪空格、强制小写等)。

这可能是使用
哈希的(mis)问题。看见正如上面的答案所指出的,您可能想要。

如果不了解更多约束条件,很难给出一个好的答案,但是如果您可以为每个文件的每一行存储一个哈希,那么您应该可以。至少您需要能够存储一个文件的哈希列表,然后将其排序并写入磁盘,然后您可以一起遍历这两个排序的列表

我能想象上述操作不能像编写的那样工作的唯一原因是,对于给定的输入,哈希函数并不总是给出相同的输出。您可以测试第二次运行old.csv是否会生成相同的列表。它可能与错误的空格、制表符而不是空格、不同的大写字母有关

请注意,即使哈希值相等,您也不知道行是否匹配;您只知道它们可能匹配。您仍然需要检查候选行是否匹配。(您还可能遇到输入文件中多行生成相同哈希值的情况,因此您也需要处理该情况。)


在填写<代码>哈希< /代码>变量后,应考虑将其转换为集合(<代码>哈希=集合(哈希)< /代码>)因此,您的查找可以比线性查找更快。

鉴于CSV的松散语法定义,两行在语义上可能相等,而在词汇上可能不同。不同的两行提供了一些线索,例如两行如何可以单独格式良好但不可通约。此示例显示了它们如何使用相同的方言而不是字符串等效:

0, 0
0, 0.0

更多信息将有助于更好地回答您的问题。

您需要说明您的问题到底是什么。您的描述“我需要确保一个文件中的一行不会出现在另一个文件中”与第二个循环的主体一致,即如果在hashes:print中找到hash(…)(一个interoper)“
而不是你所拥有的

我们不能告诉你“为什么上面的方法不起作用”,因为你没有告诉我们“失败得很惨”和“不起作用”的症状是什么。

我很确定“失败得很惨”一行指的是由于你当前的算法是O(N^2)而导致的时间上的失败,这对于你的文件有多大是非常糟糕的。如前所述,您可以使用
set
来解决此问题(将变为O(N)),或者如果由于某种原因无法解决此问题,则可以对哈希列表进行排序,并对其使用二进制搜索(将变为O(N log N),这也是可行的。如果您选择二进制搜索路径,则可以使用
bisect
模块

另外,有人提到,您可能会遇到哈希冲突的问题:当两行不完全相同时,两行产生相同的哈希。如果您发现这是您遇到的问题,则必须在每个哈希中存储有关在
old.csv 文件,然后找出该行并比较这两行

当前方法的另一种替代方法是预先对两个文件进行排序(可能使用某种磁盘合并排序或shell排序),并在每个文件中保留指向行的指针,比较这两行。检查它们是否匹配,如果不匹配,则将测得较小的行向前推进。此算法也是O(N log N)与O一样长(