在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
你说你能够解决它。如果你可以提供你自己的解决方案作为起点,这对其他人也是有教育意义的。 –