3 回答
![?](http://img1.sycdn.imooc.com/54584c5e0001491102200220-100-100.jpg)
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]
![?](http://img1.sycdn.imooc.com/54585094000184e602200220-100-100.jpg)
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)。
![?](http://img1.sycdn.imooc.com/545861b80001d27c02200220-100-100.jpg)
TA贡献1851条经验 获得超3个赞
你可以试试 :
from collections import Counter
counts = Counter(mylist)
new_list = sorted(mylist, key=lambda x: (counts[x], x), reverse=True)
添加回答
举报