2014-10-10 67 views
1

我有一個元素列表:[ 3, 3, 6, 6, 6, 5, 5, 8 ],並且需要按元素的頻率對它進行排序以獲得此結果:[ 6, 6, 6, 3, 3, 5, 5, 8 ]中的幾個元素具有相同的頻率按值排序。你能找到比這更短的方式嗎?在Python中,如何按元素的頻率對列表進行排序

import collections 
from operator import itemgetter, attrgetter 

def freq_sort(arr): 
    counter=collections.Counter(arr) 
    com = sorted(counter.most_common(), key=itemgetter(1,0), reverse=True) 
    com = map(lambda x: [x[0]] * x[1], com) 
    return [item for sublist in com for item in sublist] 
+0

屬於codereview.stackexchance。 – 2014-10-10 09:20:10

+0

定義'更短'。由Darth Kotik提出的答案在字符方面較短,但它不必在列表中每個唯一元素執行一個附加循環。作爲一個側面說明,值得注意的是,如果在具有可變元素的列表上使用,您給出的解決方案會產生問題。 – Dunes 2014-10-10 09:29:24

回答

6

試試這個

>>> old_list = [ 3, 3, 6, 6, 6, 5, 5, 8 ] 
new_list = sorted(old_list, key = old_list.count, reverse=True) 
>>> new_list 
[6, 6, 6, 3, 3, 5, 5, 8] 
+3

當計數相等時,這不會按值排序。還有list.count作爲關鍵函數不是很有效率(使得排序O(N * N)) – 2014-10-10 09:28:51

+0

你可以做一些基準測試來展示如何將執行時間與有問題的解決方案進行比較嗎? – mnowotka 2014-10-10 09:29:57

+0

雖然如果'old_list'的長度是可觀的,你會想記憶'old_list.count'。 – jacg 2014-10-10 09:30:30

0

做兩類往往比一個lambda函數的額外開銷更快。這工作,因爲Python的排序是穩定

>>> from collections import Counter 
>>> L = [ 3, 3, 6, 6, 6, 5, 5, 8 ] 
>>> c = Counter(L) 
>>> sorted(sorted(L), key=c.get, reverse=True) 
[6, 6, 6, 3, 3, 5, 5, 8] 

第二次排序是非常快的,因爲現在數據已經部分排序其中timsort的過人之處。

1

這是在線路方面有點短計數和排序第一的計數,然後按值:

import collections 
arr = [ 3, 3, 6, 6, 6, 5, 5, 8 ] 
counter = collections.Counter(arr) 
sorted(arr, key=lambda x: (counter[x], x), reverse=True) 
+0

應該是'(counter [x],-x)'以獲得正確的順序 – 2014-10-10 09:45:43

1

的collections.Counter方法most_common()你想要做什麼差不多。它返回按頻率排序的對(值,頻率)。你需要你的清單按照價值排序;該方法不保證它(規範說,當頻率相同時,值的順序是任意的)。所以我們必須將它傳遞給sorted()函數。

下面的代碼:

from collections import Counter 

l = [ 3, 3, 6, 6, 6, 5, 5, 8 ] 
c = Counter(l) 
sc = sorted(c.most_common(), key=lambda x: (-x[1], x[0])) # sorting happens here 
sl = [([v] * n) for (v, n) in sc] 
ss = sum(sl, []) 
print(ss) 

該方法具有比它在時間上只O(米日誌m),其中m是一個數在升不同值的運行的其它方法的優點。其他方法將在時間O(n log n)中運行,其中n是長度o l,總是大於或等於不同值的數量。你將基本上使用桶排序算法。

相關問題