在Python中按次要条件对Counter集合进行排序
我在使用 Python 3.3.x
的时候,有一个 Counter
对象,我想对它进行排序。
我知道可以用 .most_common(x)
方法来获取最常见的元素,但如果有多个元素的数量相同,我希望它们的键能够按字母顺序排序。
有没有办法可以做到这一点呢?也就是说,能不能设置一个这样的“平局规则”?
2 个回答
当我们需要根据多个选项进行排序,并且在出现相同情况时还要决定排序顺序时,可以使用sorted()函数和一个叫做lambda的功能来处理这个问题,具体是在'keys'参数上应用。
result=sorted(result,key=lambda x: (-x[2],x[0],x[1]))
这里的'-'
符号表示我们要先按照结果中的第3个元素进行降序排序,也就是说从大到小排。接着x[0]
和x[1]
说明如果有相同的情况,就要按照升序的顺序来排x[0]
和x[1]
,而且要严格按照这个顺序来处理。更多信息可以参考这里
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)]
我们让 sorted
对 most_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
会变成 -1
,3
会变成 -3
。这样就会把最小的元素放在最前面。因为我们得到了 -3
对应的 3,所以 3 会在最前面,2
紧随其后,1
在最后。所以结果变成了 [3, 2, 1]
。
我们用同样的技巧来根据元素中的两个项目进行排序。我们首先按计数值降序排序,如果计数值相同,再按键升序排序。