Pythonには、リストがあります。
L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
最も多く発生したアイテムを特定したい。私はそれを解決することができますが、そうするための最速の方法が必要です。これに対する素晴らしいPythonicの答えがあることを知っています。
Pythonバージョン2.5以降で動作するdefaultdict
ソリューションは次のとおりです。
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]
その後、6つの4と6つの7があります。ただし、結果は(4, 6)
すなわち6つの4。
from collections import Counter
most_common,num_most_common = Counter(L).most_common(1)[0] # 4, 6 times
古いPythonバージョン(<2.7)の場合、 this receipe を使用して Counter
クラスを取得できます。
キー_list.count
_を持つ最も簡単な解決策max()
を誰も言及していないことに驚いています:
_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で動作しますが、頻度ではなく最も頻度の高い項目のみを返すことに注意してください。また、drawの場合(つまり、最も頻繁に結合されるアイテム)単一のアイテムのみが返されます。
max()
を使用する時間の複雑さは、 PM 2Ring コメントとしてCounter.most_common(1)
を使用するよりも劣りますが、このアプローチはC
の迅速な実装とこのアプローチは、短いリストの場合は最速ですが、大きなリストの場合は遅くなります(Python 3.6のタイミングはIPython 5.3に示されています)。
_In [1]: from collections import Counter
...:
...: def f1(lst):
...: return max(lst, key = lst.count)
...:
...: def f2(lst):
...: return Counter(lst).most_common(1)
...:
...: lst0 = [1,2,3,4,3]
...: lst1 = lst0[:] * 100
...:
In [2]: %timeit -n 10 f1(lst0)
10 loops, best of 3: 3.32 us per loop
In [3]: %timeit -n 10 f2(lst0)
10 loops, best of 3: 26 us per loop
In [4]: %timeit -n 10 f1(lst1)
10 loops, best of 3: 4.04 ms per loop
In [5]: %timeit -n 10 f2(lst1)
10 loops, best of 3: 75.6 us per loop
_
あなたの質問で、あなたはそれをする最も速い方法を求めました。特に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」メソッドのコストとインプレースアドの損失が加算されます(生成されたコードの検査は演習として残されます)。
ただし、変更されたテストデータでは、一意の項目値の数は変更されなかったため、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
バージョンよりも依然として低速です。
これらの例のポイントは、最適なソリューションを作成することではありません。ポイントは、one最適な一般解が存在しないことが多いということです。さらに、他のパフォーマンス基準があります。メモリ要件はソリューション間で大幅に異なり、入力のサイズが大きくなると、メモリ要件がアルゴリズム選択の最優先要因になる場合があります。
結論:それはすべて依存しており、測定する必要があります。
おそらく most_common() メソッド
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
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 __== '__main__':
from timeit import timeit
print(timeit("occurrence()", setup = "from __main__ import occurrence", number = 20000))
出力(最適なもの):
0.1893607140000313
ライブラリまたはセットなしの簡単な方法
def mcount(l):
n = [] #To store count of each elements
for x in l:
count = 0
for i in range(len(l)):
if x == l[i]:
count+=1
n.append(count)
a = max(n) #largest in counts list
for i in range(len(n)):
if n[i] == a:
return(l[i],a) #element,frequency
return #if something goes wrong
私の(単純な)コード(Pythonを勉強する3か月):
def more_frequent_item(lst):
new_lst = []
times = 0
for item in lst:
count_num = lst.count(item)
new_lst.append(count_num)
times = max(new_lst)
key = max(lst, key=lst.count)
print("In the list: ")
print(lst)
print("The most frequent item is " + str(key) + ". Appears " + str(times) + " times in this list.")
more_frequent_item([1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67])
出力は次のようになります。
In the list:
[1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
The most frequent item is 4. Appears 6 times in this list.
素敵に見え、shortリストに対して高速な別のソリューションを投入したいと思います。
def mc(seq=L):
"max/count"
max_element = max(seq, key=seq.count)
return (max_element, seq.count(max_element))
Ned 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}
発生頻度が最も高い:3
文字は次のとおりです。
e
l
シンプルで最高のコード:
def max_occ(lst,x):
count=0
for i in lst:
if (i==x):
count=count+1
return count
lst=[1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
x=max(lst,key=lst.count)
print(x,"occurs ",max_occ(lst,x),"times")
出力: 4は6回発生します