繁体   English   中英

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

[英]Efficient and accurate way to compact and compare Python lists?

我正在尝试在两个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之后不会散列到相同的值。 我将在下面的一些建议中尝试hashlib 我也不能对原始文件执行哈希,因为下面的两行包含相同的数据,但行上的字符不同:

1, 2.3, David S, Monday
1, 2.3, "David S", Monday

我也在做像字符串剥离这样的事情,以使数据更加统一,但似乎无济于事。 我不是在寻找一个非常智能的差异逻辑,即00.0相同。

编辑2:

问题解决了。 基本上工作的是我需要更多的预格式化,如转换int和浮点数,等等我需要更改我的散列函数。 这些变化似乎都对我有用。

在不了解您的约束条件的情况下很难给出一个很好的答案,但如果您可以为每个文件的每一行存储哈希值,那么您应该没问题。 至少,您需要能够存储一个文件的哈希列表,然后您可以将其排序并写入磁盘,然后您可以一起浏览两个排序列表。

我可以想象上面没有写入的唯一原因是因为你的散列函数并不总是为给定的输入提供相同的输出。 您可以测试通过old.csv的第二次运行生成相同的列表。 它可能与错误的空格,标签 - 代替空格,不同的大写,“自动化

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

填充hashes变量后,应考虑将其转换为集合( hashes = set(hashes) ),以便查找比线性更快。

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

0, 0
0, 0.0

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

关于“悲惨失败”的含义,需要更多的信息。 如果你没有在两者之间得到正确的比较,也许Hashlib可能会解决这个问题。

我之前在使用内置哈希库时遇到了麻烦,并用它解决了它。

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

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

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

当前方法的另一种方法是预先对这两个文件进行排序(使用某种类型的合并排序到磁盘或shell排序),并保持指向每个文件中的行,比较两行。 检查它们是否匹配,如果不匹配则推进测得较小的线。 只要O(N log N)方法用于排序,该算法也是O(N log N)。 也可以通过将每个文件放入数据库并让数据库对它们进行排序来完成排序。

这可能是(错误)使用hash 看到这个问题 ; 正如答案所指出的那样,你可能想要hashlib

你需要说出你的问题究竟是什么。 您的描述“我需要确保一个文件中的一行不会出现在另一个文件中”与第二个循环的主体是一致的, if hash(...) in hashes: print "Found (an interloper)"而不是你有什么。

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

您是否考虑过运行某种类型(如果可能的话) - 当然,您必须经历两次 - 但可能会解决内存问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM