在python中检查重复项的最快方法是什么?

时间:2012-05-12 19:22:38

标签: python dictionary hashmap set duplicates

使用字典似乎很理想。

e.g:

history = {}
for i in collection:
    if i not in history:
        history[i] = None
        # fancy computation here

使用set()类型会一样快; set()不要求我向哈希键添加愚蠢的无值。

3 个答案:

答案 0 :(得分:6)

是的,你应该使用一套。


  

使用set()类型会一样快;

不,它不会那么快。它将更快


<强>更新

有些人发布了基准测试,显示集合比dict慢。我认为这有点令人惊讶,因为它们基本上具有相同的底层实现,除了set更简单。我认为我找到了缓慢的原因:

def set_way():
    my_set = set()
    my_set_add = my_set.add   # remember the method
    for ele in x:
        if ele not in my_set:
            my_set_add(ele)   # call the method directly

结果:

dict time : 1.896939858077399
set time : 1.8587076107880456

现在设定的速度略快,正如预期的那样。

答案 1 :(得分:3)

字典似乎更快。

import timeit
import random as rn

x  = [rn.choice(xrange(10000)) for i in xrange(1000)]

def set_way():
    my_set = set()
    for ele in x:
        if ele in my_set:
            return True
        else:
            my_set.add(ele)
    else:
        return False

def dict_way():
    dicto = {}
    for ele in x:
        if ele in dicto:
            return True
        else:
            dicto[ele] = None
    else:
        return False



num = 10000

set_time = timeit.timeit(set_way, number = num)
print 'set time :', set_time
dict_time = timeit.timeit(dict_way, number = num)
print 'dict time :', dict_time

结果:

set time : 0.619757678699
dict time : 0.466664548148

答案 2 :(得分:1)

Dicts更快,但只是轻微的:

import timeit

setup = """
x = range(10000)
s = set(range(5000))
d = dict.fromkeys(range(5000))
"""

print '# set', timeit.timeit('for i in x: z = i in s', setup, number=1000)
print '# dic', timeit.timeit('for i in x: z = i in d', setup, number=1000)

# set 1.18897795677
# dic 1.1489379406

尽管如此,除非性能绝对至关重要,否则为了便于阅读,您应该使用集合。

当然,正如你的问题所暗示的,我们谈的是可洗类型。不可用的类型,如容器,需要其他技术。

为了完整起见,这里有不同修改方法的基准:

import timeit

setup = """
x = range(10000)
s = set(range(5000))
d = dict.fromkeys(range(5000))

add_method = s.add
"""

print '# set-add     ', timeit.timeit('for i in x: s.add(i)', setup, number=1000)
print '# set-closure ', timeit.timeit('for i in x: add_method(i)', setup, number=1000)
print '# dict []     ', timeit.timeit('for i in x: d[i]=None', setup, number=1000)
print '# d.setdefault', timeit.timeit('for i in x: d.setdefault(i)', setup, number=1000)

# set-add      1.96829080582
# set-closure  1.2261030674
# dict []      0.982795000076
# d.setdefault 2.27355480194

dict[i]是最快的,但这次并不奇怪,因为不涉及函数调用。