標籤:

python 獲得列表中每個元素出現次數的最快方法?

如題。假設有一個列表,裡面是100萬個元素。欲將每個元素和其出現次數成對放入一個字典(dictionary)中。

以下是一種常規做法:

dic = {}

for i in list:

dic[i] = list.count(i)

但發現非常耗時,一秒鐘只能遍歷幾百個元素。

想知道有木有更好的方法,能夠降低時間複雜度。


樓主這個問題應用場景中使用的還挺廣,我之前就多次遇到這樣的問題,最開始我也是傻瓜式地採用自己一個一個往dict裡面存,然後發現實在是太**慢了,後來也用了樓上說的collections庫,發現比傻瓜式的確快了很多,,然而!這種方式並不是理想的方式,直到我知道了有個numpy庫,裡面有很多對科學計算相關的函數封裝,簡直是屢試不爽。。好吧進入正題,下面簡短的代碼即展示了各種方式對樓主問題的解決方式,還對各方法性能進行了簡單評測(註:我也只是個python新手,一直學習中,如有錯誤,請大家不吝賜教):

import collections
import numpy as np
import random
import time

def list_to_dict(lst):
dic = {}
for i in lst:
dic[i] = lst.count(i)
return dic

def collect(lst):
return dict(collections.Counter(lst))

def unique(lst):
return dict(zip(*np.unique(lst, return_counts=True)))

def generate_data(num=1000000):
return np.random.randint(num / 10, size=num)

if __name__ == "__main__":
t1 = time.time()
lst = list(generate_data())
t2 = time.time()
print("generate_data took : %sms" % (t2 - t1)) # 本機實測0.12ms

t1 = t2
d1 = unique(lst)
t2 = time.time()
print("unique took : %sms" % (t2 - t1)) # 本機實測0.42ms

t1 = t2
d2 = collect(lst)
t2 = time.time()
print("collect took : %sms" % (t2 - t1)) # 本機實測1.25ms

t1 = t2
d3 = list_to_dict(lst)
t2 = time.time()
print("list_to_dict took : %sms" % (t2 - t1)) # 本機實測...太慢了測不下去了

assert(d1 == d2)
assert(d1 == d3)

結論:要善於利用大神們造的輪子(標準庫 擴展庫 and 其他包),雖然不造這個numpy是誰造的,但是真是太強大了,另附上numpy.unique這個函數的官方鏈接,還有其他妙用的哈哈:numpy.unique


使用標準庫提供的collections

基本用法:

import collections
lst = [] # lst存放所謂的100萬個元素
d = collections.Counter(lst)
# 瞬間出結果
for k in d:
# k是lst中的每個元素
# d[k]是k在lst中出現的次數


from collections import Counter

words = [
look, into, my, eyes, look, into, my, eyes,
the, eyes, the, eyes, the, eyes, not, around, the,
eyes, "dont", look, around, the, eyes, look, into,
my, eyes, "youre", under
]

print (Counter(words))
Counter({eyes: 8, the: 5, look: 4, into: 3, my: 3, around: 2, not: 1, "dont": 1, "youre": 1, under: 1})
print (Counter(words).most_common(4))
[(eyes, 8), (the, 5), (look, 4), (into, 3)]

君子性非異也,善假於物也


推薦閱讀:

TAG:Python | 演算法 |