为了账号安全,请及时绑定邮箱和手机立即绑定

按频率对列表进行排序

按频率对列表进行排序

慕仙森 2023-10-06 19:28:51
我想按频率降序对列表进行排序。如果两个值的频率相同,那么我还希望这两个值按降序排列。例如,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)
查看完整描述

3 回答

?
慕娘9325324

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]


查看完整回答
反对 回复 2023-10-06
?
墨色风雨

TA贡献1853条经验 获得超6个赞

为什么

sorted(mylist, key=lambda x: (mylist.count, -x), reverse=True)

出错?

它比较键,因此例如两个值31成为对(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)。


查看完整回答
反对 回复 2023-10-06
?
皈依舞

TA贡献1851条经验 获得超3个赞

你可以试试 :


from collections import Counter


counts = Counter(mylist)

new_list = sorted(mylist, key=lambda x: (counts[x], x), reverse=True)


查看完整回答
反对 回复 2023-10-06
  • 3 回答
  • 0 关注
  • 136 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信