我想按列表的降序对列表进行排序。如果两个值的频率相同,那么我也希望这两个值的降序。
例如,
mylist = [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].
如果我使用
sorted(mylist,key = mylist.count,reverse = True)
我会得到
[4,4,4,4,4,4,3,3,3,3,3,2,2,2,5,5,5,1,1];
我尝试过
sorted(mylist,key = lambda x:(mylist.count,-x),reverse = True)
但是我认为出了点问题,它只会给我结果:
[1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5].
所以我的问题是如何获得想要的结果以及为什么会得到结果
[1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5]
如果我使用
sorted(mylist,key = lambda x:(mylist.count,-x),reverse = True)
答案 0 :(得分:1)
使用计数器获取频率,然后按其给出的频率排序:
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]
答案 1 :(得分:0)
您可以尝试:
from collections import Counter
counts = Counter(mylist)
new_list = sorted(mylist, key=lambda x: (counts[x], x), reverse=True)
答案 2 :(得分:0)
为什么
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
的崩溃。元组之间进行比较的实际方式是通过first finding a difference,这是通过检查平等来完成的。并且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
代替mylist.count
会更有效,因为后者会使解取O(n 2 ),而不是O(n log n)。