在Python中按次要条件对Counter集合进行排序

10 投票
2 回答
3556 浏览
提问于 2025-04-18 02:30

我在使用 Python 3.3.x 的时候,有一个 Counter 对象,我想对它进行排序。
我知道可以用 .most_common(x) 方法来获取最常见的元素,但如果有多个元素的数量相同,我希望它们的键能够按字母顺序排序。
有没有办法可以做到这一点呢?也就是说,能不能设置一个这样的“平局规则”?

2 个回答

1

当我们需要根据多个选项进行排序,并且在出现相同情况时还要决定排序顺序时,可以使用sorted()函数和一个叫做lambda的功能来处理这个问题,具体是在'keys'参数上应用。

result=sorted(result,key=lambda x: (-x[2],x[0],x[1]))

这里的'-'符号表示我们要先按照结果中的第3个元素进行降序排序,也就是说从大到小排。接着x[0]x[1]说明如果有相同的情况,就要按照升序的顺序来排x[0]x[1],而且要严格按照这个顺序来处理。更多信息可以参考这里

16

collections.Counter 实际上是一种字典,它们使用了一种叫做哈希的技术,所以我们不能按顺序访问它们。既然不能按顺序访问,字典的排序就不可能了。不过,你可以把它转换成一个包含键和值的元组列表,然后再进行排序。例如,

print(Counter('abracadabra').most_common())
# [('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]
print(sorted(Counter('abracadabra').most_common(), key=lambda x: (-x[1], x[0])))
# [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]

我们让 sortedmost_common 返回的 (key, value) 数据进行排序。我们想确保这些项目按 value 降序排列,同时按 key 升序排列。所以,我们在这里用了一点小技巧。sorted 会对要排序的每个元素调用我们传递给 key 参数的函数。这个函数返回的值将用于与其他元素进行比较。在我们的例子中,key 函数是这样的:

lambda x: (-x[1], x[0])

这里,x 最终会获取所有元素,并交换第一个和第二个元素的位置,同时将实际的计数部分取反。因为 sorted 默认是按升序排序的,所以我们把最大的数变成最小的,反之亦然。例如,

[2, 3, 1]

如果你想按升序排序,sorted 会把最小的元素放在最前面,第二小的放在第二位,以此类推,直到最大的元素。在我们的例子中,结果是 [1, 2, 3]。要按降序排序,我们就让它们的取反值来表示实际的数字。

sorted([2, 3, 1], key=lambda x: -x)

现在,当 sorted 处理 2 时,它会调用 key 函数来获取用于比较的值,返回 -2,同样 1 会变成 -13 会变成 -3。这样就会把最小的元素放在最前面。因为我们得到了 -3 对应的 3,所以 3 会在最前面,2 紧随其后,1 在最后。所以结果变成了 [3, 2, 1]

我们用同样的技巧来根据元素中的两个项目进行排序。我们首先按计数值降序排序,如果计数值相同,再按键升序排序。

撰写回答