我有一个很大的DOI列表,我需要最有效的方法来识别重复的DOI(即打印索引和重复值的DOI。) DOI的数组可以由500,000 + DOI组成。我目前的方法是这个(inspired by this answer):
from collections import defaultdict
D = defaultdict(list)
for i,item in enumerate(doiList):
D[item].append(i)
D = {k:v for k,v in D.items() if len(v)>1}
print (D)
是否有更有效的处理方式?
样本DOI列表:
doiList = ['10.1016/j.ijnurstu.2017.05.011 [doi]','10.1016/j.ijnurstu.2017.05.011 [doi]' ,'10.1167/iovs.16-20421 [doi]', '10.1093/cid/cix478 [doi]', '10.1038/bjc.2017.133 [doi]', '10.3892/or.2017.5646 [doi]', '10.1177/0961203317711009 [doi]', '10.2217/bmm-2017-0087 [doi]', '10.1007/s12016-017-8611-x [doi]', '10.1007/s10753-017-0594-5 [doi]', '10.1186/s13601-017-0150-2 [doi]', '10.3389/fimmu.2017.00515 [doi]', '10.2147/JAA.S131506 [doi]', '10.2147/JAA.S128431 [doi]', '10.1038/s41598-017-02293-z [doi]', '10.18632/oncotarget.17729 [doi]', '10.1073/pnas.1703683114 [doi]', '10.1096/fj.201600857RRR [doi]', '10.1128/AAC.00020-17 [doi]', '10.1016/j.jpain.2017.04.011 [doi]', '10.1016/j.jaip.2017.04.029 [doi]', '10.1016/j.anai.2017.04.021 [doi]', '10.1016/j.alit.2017.05.001 [doi]']
答案 0 :(得分:2)
尝试将它们存储在set
中。您可以将重复项附加到单个列表中,这可能会加快速度:
seen = set()
dupes = []
for i, doi in enumerate(doiList):
if doi not in seen:
seen.add(doi)
else:
dupes.append(i)
此时,seen
包含所有不同的doi值,而dupes
包含重复值的所有第2,第3等索引。您可以在doiList
中查找它们以确定哪个索引对应于哪个值。
为了获得更多性能,您可以缓存方法:
seen = set()
seen_add = seen.add
dupes = []
dupes_append = dupes.append
for i, doi in enumerate(doiList):
if doi not in seen:
seen_add(doi)
else:
dupes_append(i)
答案 1 :(得分:1)
这是一个完整的解决方案,可以返回与您的示例相同的数据集,速度提高两倍以上(以牺牲内存为代价):
def identify_duplicates(data):
lookup = {} # store our quick lookup here
result = {} # store for our final result
for i, v in enumerate(data):
if v in lookup: # if already in the lookup table it's a duplicate
if v not in result: # add it to the result set
result[v] = lookup[v]
lookup[v][1] += 1 # increase duplicate count
else:
lookup[v] = [i, 0] # default state for non-duplicates
return result
print(identify_duplicates(doiList))
# prints: {'10.1016/j.ijnurstu.2017.05.011 [doi]': [0, 1]}
存储的索引是找到的副本的第一个匹配项,如示例中所示。如果要存储所有重复索引,可以在lookup[v].append(i)
行之后添加lookup[v][1] += 1
,但数据可能看起来很奇怪(结构将是[first_index, number_of_occurrences, second_index, third_index...]
)
相反,只需翻转lookup[v]
修改中存储的参数 - lookup[v] = [0, i]
而不是lookup[v] = [i, 0]
和lookup[v][0] += 1
而不是lookup[v][1] += 1
,然后lookup[v].append(i)
它会以[number_of_occurrences, first_index, second_index, third_index...]
的形式给你一个很好的结果。