在Python最大出現的項目,我有一個列表:Python-發現列表中的
L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
我想,以確定發生的次數最多的項目。我能夠解決它,但我需要最快的方式來做到這一點。我知道這是一個很好的Pythonic答案。
在Python最大出現的項目,我有一個列表:Python-發現列表中的
L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
我想,以確定發生的次數最多的項目。我能夠解決它,但我需要最快的方式來做到這一點。我知道這是一個很好的Pythonic答案。
這裏是一個defaultdict
解決方案,將與Python版本2.5及以上的工作:
from collections import defaultdict
L = [1,2,45,55,5,4,4,4,4,4,4,5456,56,6,7,67]
d = defaultdict(int)
for i in L:
d[i] += 1
result = max(d.iteritems(), key=lambda x: x[1])
print result
# (4, 6)
# The number 4 occurs 6 times
注意如果L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 7, 7, 7, 7, 7, 56, 6, 7, 67]
則有六個4S和六個7S。然而,結果將是(4, 6)
,即六個4。
很小,但'itemgetter(1)'可能比'lambda x:x [1]'結構在簡單性和速度方面都更好。即請參閱http://docs.python.org/howto/sorting.html#operator-module-functions –
from collections import Counter
most_common,num_most_common = Counter(L).most_common(1)[0] # 4, 6 times
對於老版本的Python(< 2.7),你可以使用this receipe得到Counter
類。
有關詳細信息,請參閱[Counter docs](http://docs.python.org/dev/library/collections.html#collections.Counter)。 – SiggyF
這個解決方案非常優雅,但目前,另一個爲我工作。 – zubinmehta
也許most_common()方法
在你的問題中,你問最快的方法來做到這一點。正如一再被證明的那樣,特別是在Python中,直覺並不是一個可靠的指南:你需要測量。
下面是幾種不同的實現一個簡單的測試:
import sys
from collections import Counter, defaultdict
from itertools import groupby
from operator import itemgetter
from timeit import timeit
L = [1,2,45,55,5,4,4,4,4,4,4,5456,56,6,7,67]
def max_occurrences_1a(seq=L):
"dict iteritems"
c = dict()
for item in seq:
c[item] = c.get(item, 0) + 1
return max(c.iteritems(), key=itemgetter(1))
def max_occurrences_1b(seq=L):
"dict items"
c = dict()
for item in seq:
c[item] = c.get(item, 0) + 1
return max(c.items(), key=itemgetter(1))
def max_occurrences_2(seq=L):
"defaultdict iteritems"
c = defaultdict(int)
for item in seq:
c[item] += 1
return max(c.iteritems(), key=itemgetter(1))
def max_occurrences_3a(seq=L):
"sort groupby generator expression"
return max(((k, sum(1 for i in g)) for k, g in groupby(sorted(seq))), key=itemgetter(1))
def max_occurrences_3b(seq=L):
"sort groupby list comprehension"
return max([(k, sum(1 for i in g)) for k, g in groupby(sorted(seq))], key=itemgetter(1))
def max_occurrences_4(seq=L):
"counter"
return Counter(L).most_common(1)[0]
versions = [max_occurrences_1a, max_occurrences_1b, max_occurrences_2, max_occurrences_3a, max_occurrences_3b, max_occurrences_4]
print sys.version, "\n"
for vers in versions:
print vers.__doc__, vers(), timeit(vers, number=20000)
我的機器上的結果:
2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
dict iteritems (4, 6) 0.202214956284
dict items (4, 6) 0.208412885666
defaultdict iteritems (4, 6) 0.221301078796
sort groupby generator expression (4, 6) 0.383440971375
sort groupby list comprehension (4, 6) 0.402786016464
counter (4, 6) 0.564319133759
所以看來Counter
解決方案是不是最快的。而且,在這種情況下,至少,groupby
更快。 defaultdict
是好的,但你付出一點點爲它的方便;使用dict
與get
的速度稍快。
如果列表大得多,會發生什麼?上面添加L *= 10000
到測試和減少重複次數,以200:
dict iteritems (4, 60000) 10.3451900482
dict items (4, 60000) 10.2988479137
defaultdict iteritems (4, 60000) 5.52838587761
sort groupby generator expression (4, 60000) 11.9538850784
sort groupby list comprehension (4, 60000) 12.1327362061
counter (4, 60000) 14.7495789528
現在defaultdict
是明顯的贏家。因此,'get'方法的成本和inplace add的損失可能會相加(對生成的代碼的檢查僅作爲練習)。
但是對於修改後的測試數據,唯一項目值的數量沒有變化,所以推測dict
和defaultdict
比其他實現具有優勢。那麼,如果我們使用更大的列表,但會大幅增加獨特項目的數量,會發生什麼?與更換L的初始化:
LL = [1,2,45,55,5,4,4,4,4,4,4,5456,56,6,7,67]
L = []
for i in xrange(1,10001):
L.extend(l * i for l in LL)
dict iteritems (2520, 13) 17.9935798645
dict items (2520, 13) 21.8974409103
defaultdict iteritems (2520, 13) 16.8289561272
sort groupby generator expression (2520, 13) 33.853593111
sort groupby list comprehension (2520, 13) 36.1303369999
counter (2520, 13) 22.626899004
所以現在Counter
明顯快於groupby
解決方案,但仍比iteritems
版本dict
和defaultdict
慢。
這些例子的重點不是產生最佳解決方案。重點是經常沒有一個最佳通用解決方案。另外還有其他性能標準。這些解決方案中的內存要求會有很大差異,並且隨着輸入大小的增加,內存需求可能成爲算法選擇的首要因素。底線:這一切都取決於你需要測量。
這是一個夢幻般的答案,是任何解決方案的時間測試替代品的大量粉絲。謝謝Ned。 – Eugene
我很驚訝沒有人提到的最簡單的解決方案,max()
用鑰匙list.count
:
max(lst,key=lst.count)
例子:
>>> lst = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
>>> max(lst,key=lst.count)
4
這工作在Python 3或2,但要注意它只返回最頻繁的項目,而不是頻率。而且,在繪製(即聯合最頻繁項目)的情況下,僅返回單個項目。
我找到max()
辦法是約快兩倍,Counter.most_common(1)
:
from collections import Counter
from timeit import timeit
def f1(lst):
return max(lst, key = lst.count)
def f2(lst):
return Counter(lst).most_common(1)
lst = range(100000)
timeit(lambda: f1(lst), number = 1000)
# 28.13
timeit(lambda: f2(lst), number = 1000)
# 59.01
我使用Python 3.5.2此功能得到groupby
最好的結果從itertools
模塊:
from itertools import groupby
a = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
def occurrence():
occurrence, num_times = 0, 0
for key, values in groupby(a, lambda x : x):
val = len(list(values))
if val >= occurrence:
occurrence, num_times = key, val
return occurrence, num_times
occurrence, num_times = occurrence()
print("%d occurred %d times which is the highest number of times" % (occurrence, num_times))
輸出:
4 occurred 6 times which is the highest number of times
Tes與timeit
模塊的timeit
。
我用這個腳本爲我的測試與number= 20000
:
from itertools import groupby
def occurrence():
a = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
occurrence, num_times = 0, 0
for key, values in groupby(a, lambda x : x):
val = len(list(values))
if val >= occurrence:
occurrence, num_times = key, val
return occurrence, num_times
if __name__ == '__main__':
from timeit import timeit
print(timeit("occurrence()", setup = "from __main__ import occurrence", number = 20000))
輸出(最好的):
0.1893607140000313
我想在另一個解決方案,看起來不錯,是快扔短的名單。
def mc(seq=L):
"max/count"
max_element = max(seq, key=seq.count)
return (max_element, seq.count(max_element))
您可以基準本與斯內德Deily提供的代碼,這將給你這些結果是最小的測試案例:
3.5.2 (default, Nov 7 2016, 11:31:36)
[GCC 6.2.1 20160830]
dict iteritems (4, 6) 0.2069783889998289
dict items (4, 6) 0.20462976200065896
defaultdict iteritems (4, 6) 0.2095775119996688
sort groupby generator expression (4, 6) 0.4473949929997616
sort groupby list comprehension (4, 6) 0.4367636879997008
counter (4, 6) 0.3618192010007988
max/count (4, 6) 0.20328268999946886
但要注意,這是低效的,因而得到真的慢大列表!
以下是我提出的解決方案,如果字符串中有多個字符都具有最高的頻率。
mystr = input("enter string: ")
#define dictionary to store characters and their frequencies
mydict = {}
#get the unique characters
unique_chars = sorted(set(mystr),key = mystr.index)
#store the characters and their respective frequencies in the dictionary
for c in unique_chars:
ctr = 0
for d in mystr:
if d != " " and d == c:
ctr = ctr + 1
mydict[c] = ctr
print(mydict)
#store the maximum frequency
max_freq = max(mydict.values())
print("the highest frequency of occurence: ",max_freq)
#print all characters with highest frequency
print("the characters are:")
for k,v in mydict.items():
if v == max_freq:
print(k)
輸入: 「你好人」
輸出:
{'o': 2, 'p': 2, 'h': 1, ' ': 0, 'e': 3, 'l': 3}
occurence的最高頻率:3
字符是:
e
l
你說你能夠解決它。如果你可以提供你自己的解決方案作爲起點,這對其他人也是有教育意義的。 –