我想比较一个列表的值是否存在于其他列表的值中。它们是巨大的(50k +项目,来自数据库)。
我还想将重复的记录标记为duplicate = True,并将它们保存在表中以供日后参考。
这里列表如何:
n_emails=[db_id,checksum for id,checksum in search_results]
#I want to compare checksum if exist inside same list or other list and retrieve id (db_id , if exist)
#example : n_emails= [[1,'CAFEBABE010'],[2,'bfeafe3df1ds],[3,'deadbeef101'],[5,'CAFEBABE010']]
#in this case i want to retrive id 1 and 5 coz they are same checksum
for m in n_emails:
dups=_getdups(n_emails,m[1],m[0])
n_dups=[casesdb.duplicates.insert( **dup ) for dup in dups]
if n_dups:
print "Dupe Found"
casesdb(casesdb.email_data.id == m[0]).update(duplicated=True)
def _getdups(old_lst,em_md5,em_id):
dups=[]
for old in old_lst:
if em_md5==old[0] and old[1]!=em_id:
dups.append(dict(org_id=old[1],md5hash=old[0],dupID=em_id,))
return dups
但它似乎太长了并且在更大的列表中(50k vs 50k记录+)它运行超过5000秒并且从未完成,似乎永远不会结束循环? 我运行的服务器有4 GB的内存和4个内核。显然我做错了。
请帮助..非常感谢!
Dict Index Mapping速度快得多! (当没有索引mysql表时,请注意我没有测试索引表)。
它的20秒vs 30毫秒= 20 * 1000/30 = 666次! LOL
答案 0 :(得分:2)
你最好用SQL查找重复项。例如,请参阅this page describing how to find duplicates。
将所有这些结果提取到Python中并处理它们的速度永远不会很快,但如果必须,最好的办法是给ID校验和字典:
got_checksums = {}
for id, checksum in emails:
if checksum in got_checksums:
print id, got_checksums[checksum]
else:
got_checksums[checksum] = id
答案 1 :(得分:2)
最快的方法是使用这样的字典:
n_emails= [[1,'CAFEBABE010'],[2,'bfeafe3df1ds'],[3,'deadbeef101'],[5,'CAFEBABE010']]
d = {}
for id, hash in n_emails:
if hash not in d:
d[hash] = [id]
else:
d[hash].append(id)
for hash, ids in d:
if len(ids) > 1:
print hash, ids
这几乎是散列连接的算法
for hash, count in select hash, count(id) as num from emails group by num having num > 1:
first = None
for index, id in enumerate(select id from emails where hash=hash sort by desc id):
if index == 0:
first = id
continue
update emails set duplicate=first where id=id
将是sql / python解决方案,我将重复列并使用它来存储哪一条消息被认为是重复的
电子邮件表至少是:
create table emails (id, hash, duplicate default null)
答案 2 :(得分:2)
你做错了是:
您应该做的是在校验和上构建索引。制作一张映射checksum -> entry
的字典。插入条目时检查校验和是否已存在,如果是,则条目重复。
或者你只是使用你的数据库,他们喜欢索引。
答案 3 :(得分:1)
最后,感谢所有答案,我发现dict映射速度非常快!比SQL查询快得多。
这是我的SQL查询测试(它看起来很尴尬,但它是Web2pyDAL查询的语法)。
我测试了3500条记录,并且仅针对超过250000条记录进行了dict映射。
print "de_duping started at %s" % str( datetime.datetime.now() )
dupe_n = 0
l_dupe_n = 0
for em_hash in n_emails:
dup_ids=casesdb(casesdb.email_data.MD5Hash==em_hash[1]).select(casesdb.email_data.id)
if dup_ids>1:
dupe_n+=1
print "Email Dupes %s" % (dupe_n)
print "Local de_duping ended at %s" % str( datetime.datetime.now() )
Resullts in:
de_duping started at 2010-12-02 03:39:24.610888
Email Dupes 3067
Local de_duping ended at 2010-12-02 03:39:52.669849
大约28秒
继承人基于Dan D的基于dict的索引图
print "de_duping started at %s" % str( datetime.datetime.now() )
for id, hash in em_hash:
if hash not in dedupe_emails:
dedupe_emails[hash] = [id]
else:
dedupe_emails[hash].append( id )
dupe_n += 1
casesdb( casesdb.email_data.id == id ).update( duplicated = True )
print "Email Dupes %s" % (dupe_n)
print "Local de_duping ended at %s" % str( datetime.datetime.now() )
结果:
de_duping started at 2010-12-02 03:41:21.505235
Email Dupes 2591 # this is accurate as selecting from database regards first match as duplicate too
Local de_duping ended at 2010-12-02 03:41:21.531899
只有什么? 30毫秒!
让我们看看它对重复删除250k记录做了什么!
de_duping at 2010-12-02 03:44:20.120880
Email Dupes 93567
Local de_duping ended at 2010-12-02 03:45:12.612449
不到一分钟!!
感谢所有答案,我想选择那些指出我正确方法的人,但Dan D给了我最详细的答案!谢谢Dan!