使用字典似乎很理想。在Python中檢查重複項的最快方法是什麼?
例如爲:
history = {}
for i in collection:
if i not in history:
history[i] = None
# fancy computation here
將使用該組()類型是一樣快; set()不需要我向散列鍵添加無用的None值。
使用字典似乎很理想。在Python中檢查重複項的最快方法是什麼?
例如爲:
history = {}
for i in collection:
if i not in history:
history[i] = None
# fancy computation here
將使用該組()類型是一樣快; set()不需要我向散列鍵添加無用的None值。
是的,你應該使用一套。
將使用該組()類型是一樣快;
不,它不會一樣快。這將是更快。
更新
有人已經發布的基準顯示,集比字典慢。我認爲這有點令人驚訝,因爲它們基本上具有相同的底層實現,只是設置更簡單。我想我已經找到了緩慢的原因:
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
設置稍快,符合市場預期。
日文N3 N4 N5的速度更快,但只能勉強:
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]
是最快的,但這次一點也不奇怪,因爲沒有函數調用參與。
字典似乎更快。
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
設置較慢?令人驚訝...你有任何解釋嗎? –
我也很驚訝。也許增加設置比添加字典要慢?我很想知道自己的解釋是什麼。 – Akavall
+1用於發佈令人驚訝的性能測量結果。請參閱我的更新答案以獲得解釋。 –
爲什麼快?檢查字典中的密鑰是否需要一定的時間,它與集合的確切算法相同嗎? – TheOne
@Ramin:是的,套裝也使用哈希。集合中的項目必須是可散列的。 –
有趣的.... – TheOne