3 回答

TA貢獻1783條經驗 獲得超4個贊
使用 Counter 獲取頻率,然后按它給出的頻率排序:
from collections import Counter
def sorted_by_frequency(arr):
counts = Counter(arr)
# secondarily sort by value
arr2 = sorted(arr, reverse=True)
# primarily sort by frequency
return sorted(arr2, key=counts.get, reverse=True)
# Usage:
>>> sorted_by_frequency([1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 5, 5, 5, 4, 4, 4, 4, 4, 4])
[4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, 5, 5, 2, 2, 2, 1, 1]

TA貢獻1853條經驗 獲得超6個贊
為什么
sorted(mylist, key=lambda x: (mylist.count, -x), reverse=True)
出錯?
它比較鍵,因此例如兩個值3
和1
成為對(mylist.count, -3)
和 ,(mylist.count, -1)
并且比較將是(mylist.count, -3) < (mylist.count, -1)
。
因此,明顯的錯誤是這些對沒有預期的數字頻率。相反,他們有這個功能。而且功能不亞于它本身。
但我發現注意到當時到底發生了什么很有趣。配對比較是如何進行的?您可能認為這(a, b) < (c, d)
相當于(a < c) or (a == c and b < d)
. 事實并非如此。因為這會評估mylist.count < mylist.count
,然后你會因TypeError
. 元組相互比較的實際方式是首先找到差異,然后通過檢查相等性來完成。而且mylist.count == mylist.count
不僅不會崩潰反而會返回True
。因此,元組比較會轉到下一個索引,在那里它將找到-3
和-1
。
所以本質上你只是在做
sorted(mylist, key=lambda x: -x, reverse=True)
并且否定和reverse=True
相互抵消,所以你得到相同的結果
sorted(mylist, key=lambda x: x)
要不就
sorted(mylist)
現在如何做對呢?一種方法是調用該函數(并刪除否定):
result = sorted(mylist, key=lambda x: (mylist.count(x), x), reverse=True)
或者同時否定頻率和價值,而不是reverse=True
:
result = sorted(mylist, key=lambda x: (-mylist.count(x), -x))
另一種方法是利用排序的穩定性并使用兩種更簡單的排序(甚至可能比一種更復雜的排序更快):
result = sorted(mylist, reverse=True) result.sort(key=mylist.count, reverse=True)
請注意,這里我們不必調用mylist.count
自己,因為它是鍵,它將為我們調用。就像你的“lambda 函數”確實被調用一樣(只是不是其結果中的函數)。另請注意,我使用sorted
后跟就地sort
- 沒有必要創建另一個列表并產生與之相關的成本。
collections.Counter
盡管在所有情況下,對于長列表,使用 a代替會更有效mylist.count
,因為后者使解決方案采用 O(n 2 ) 而不是 O(n log n)。

TA貢獻1851條經驗 獲得超3個贊
你可以試試 :
from collections import Counter
counts = Counter(mylist)
new_list = sorted(mylist, key=lambda x: (counts[x], x), reverse=True)
添加回答
舉報