Python——多条件排序
问题描述
有这么一个类代表学生
class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
一张成绩表中记录了4个学生的成绩和年龄
student_objects = [
Student('john', 'B', 7),
Student('jane', 'A', 11),
Student('dave', 'B', 5),
Student('Amy', 'C', 5)
]
现在宋老师想要对这4个学生的成绩进行排序。
多条件都是升序or降序
学生成绩按照升序排序,如果成绩相同则按照年龄升序排序:
# 方法1:两次排序,先按次要条件排序
>>> temp_lst = sorted(student_objects, key=lambda x: x.age)
>>> sorted(temp_lst, key=lambda x: x.grade)
[('jane', 'A', 11), ('dave', 'B', 5), ('john', 'B', 7), ('Amy', 'C', 5)]
# 方法2:多条件lambda
>>> sorted(student_objects, key=lambda x: (not x.grade, -x.age))
[('jane', 'A', 11), ('dave', 'B', 5), ('john', 'B', 7), ('Amy', 'C', 5)]
注意,成绩使用字符串进行表示的,Python中字符串按字典序进行排序。
如果想要让学生成绩按照降序排序,成绩相同则按照年龄降序排序:
# 方法1:两次排序,先按次要条件排序
>>> temp_lst = sorted(student_objects, key=lambda x: x.age, reverse=True)
>>> sorted(temp_lst, key=lambda x: x.grade, reverse=True)
[('Amy', 'C', 5), ('john', 'B', 7), ('dave', 'B', 5), ('jane', 'A', 11)]
# 方法2:多条件lambda
>>> sorted(student_objects, key=lambda x: (x.grade, x.age), reverse=True)
[('Amy', 'C', 5), ('john', 'B', 7), ('dave', 'B', 5), ('jane', 'A', 11)]
现在出现了新的要求,想要对成绩和年龄按照不同的升降顺序进行排列。
多条件有的升序有的降序
学生成绩按照升序排列,对成绩相同的学生按照年龄进行降序排序
# 方法1:两次排序,先按次要条件排序
>>> temp_lst = sorted(student_objects, key=lambda x: x.age, reverse=True)
>>> sorted(temp_lst, key=lambda x: x.grade)
[('jane', 'A', 11), ('john', 'B', 7), ('dave', 'B', 5), ('Amy', 'C', 5)]
# 方法2:多条件lambda
>>> sorted(student_objects, key=lambda x: (x.grade, -x.age))
[('jane', 'A', 11), ('john', 'B', 7), ('dave', 'B', 5), ('Amy', 'C', 5)]
学生成绩按照降序排列,对成绩相同的学生按照年龄进行升序排序
# 方法1:两次排序,先按次要条件排序
>>> temp_lst = sorted(student_objects, key=lambda x: x.age)
>>> sorted(temp_lst, key=lambda x: x.grade, reverse=True)
[('Amy', 'C', 5), ('dave', 'B', 5), ('john', 'B', 7), ('jane', 'A', 11)]
# 方法2:多条件lambda
>>> sorted(student_objects, key=lambda x: (not x.grade, x.age))
[('Amy', 'C', 5), ('dave', 'B', 5), ('john', 'B', 7), ('jane', 'A', 11)]
降序处理
细心的读者可能已经发现,在“多条件有的升序有的降序”中,如果用“多条件lambda”的方式进行多条件排序,针对字符串类型的属性,使用not x.grade
表示降序,针对数字类型的属性,使用-x.age
表示降序。希望大家使用的时候予以重视(不过用错了的话,编译器也会给你报错的😆)。
总结
针对我们所使用的方法1
进行解释,为什么可以这样做:
因为Python中的list.sort以及sorted方法,都是稳定排序的,即不会打乱元素的相对顺序。我们可以先对次要条件进行排序,再对主要条件进行排序,达到多条件排序的目的。
在此进行引申,如果我们面对n多个条件的多条件排序如何解决呢?答案照猫画虎,在两个条件的排序模板下进行条件新增就好了。比如方法1
那么就根据这n个条件的主次关系进行多次排序,先排最次要的条件,最后排最主要的条件。
方法2
的话只需要在lambda表达式中写上n条规则即可,例如key=lambda x: (x.规则1, x.规则2, ..., x.规则n)
。