MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python列表sorted排序的灵活性体现

2021-12-274.5k 阅读

Python列表sorted排序的灵活性体现

在Python编程中,列表是一种常用的数据结构,而排序操作是对列表进行处理时经常会用到的功能。sorted()函数作为Python内置的排序工具,展现出了令人瞩目的灵活性,它不仅仅能对简单的数值列表进行常规排序,还能在各种复杂场景下发挥作用,满足多样化的排序需求。

一、对基本数据类型列表排序

  1. 整数列表排序 对于整数列表,sorted()函数能按照从小到大的顺序对列表元素进行排序。这是最基本的使用场景,代码示例如下:
    num_list = [5, 3, 8, 1, 9]
    sorted_num_list = sorted(num_list)
    print(sorted_num_list)
    
    在上述代码中,num_list是一个包含整数的列表,通过sorted(num_list)操作,得到了一个新的已排序列表sorted_num_list,输出结果为[1, 3, 5, 8, 9]
  2. 浮点数列表排序 同样地,sorted()函数也能对浮点数列表进行排序,其排序规则与整数列表类似,按照数值大小从小到大排列。示例代码如下:
    float_list = [3.14, 1.618, 2.718, 0.577]
    sorted_float_list = sorted(float_list)
    print(sorted_float_list)
    
    运行上述代码,会输出[0.577, 1.618, 2.718, 3.14]sorted()函数对浮点数列表的排序操作非常直观和有效。
  3. 字符串列表排序 当处理字符串列表时,sorted()函数会按照字典序进行排序。所谓字典序,就是按照字符在Unicode编码表中的顺序进行比较。例如:
    str_list = ['banana', 'apple', 'cherry']
    sorted_str_list = sorted(str_list)
    print(sorted_str_list)
    
    上述代码执行后,输出为['apple', 'banana', 'cherry']。这里字符串是按照首字母的字典序进行排列的,如果首字母相同,则继续比较下一个字母,以此类推。

二、sortedreverse参数实现反向排序

  1. 整数列表反向排序 在很多实际应用场景中,我们可能需要按照从大到小的顺序对列表进行排序,这时可以通过设置sorted()函数的reverse参数来实现。对于整数列表,示例代码如下:
    num_list = [5, 3, 8, 1, 9]
    sorted_num_list_desc = sorted(num_list, reverse = True)
    print(sorted_num_list_desc)
    
    上述代码中,将reverse参数设置为Truesorted()函数就会返回一个从大到小排序的新列表,输出结果为[9, 8, 5, 3, 1]
  2. 字符串列表反向字典序排序 对于字符串列表,同样可以使用reverse参数来实现反向字典序排序。例如:
    str_list = ['banana', 'apple', 'cherry']
    sorted_str_list_desc = sorted(str_list, reverse = True)
    print(sorted_str_list_desc)
    
    执行代码后,输出为['cherry', 'banana', 'apple'],实现了字符串列表按照反向字典序进行排序。

三、通过key参数自定义排序规则

  1. 根据字符串长度对字符串列表排序 在某些情况下,我们不想按照默认的字典序对字符串列表进行排序,而是希望根据字符串的长度来排序。这时可以通过sorted()函数的key参数来实现。key参数接受一个函数作为值,该函数会作用于列表的每个元素,sorted()函数会根据这个函数的返回值来进行排序。示例代码如下:
    str_list = ['banana', 'apple', 'cherry', 'date']
    sorted_by_length = sorted(str_list, key = len)
    print(sorted_by_length)
    
    在上述代码中,key = len表示将列表元素传递给len函数,sorted()函数根据每个字符串的长度来进行排序。输出结果为['date', 'apple', 'banana', 'cherry'],从短到长对字符串列表进行了排序。
  2. 根据字典的某个值对字典列表排序 假设有一个字典列表,每个字典表示一个人的信息,包含nameage等字段,现在我们希望根据age对这个列表进行排序。示例代码如下:
    people = [
        {'name': 'Alice', 'age': 25},
        {'name': 'Bob', 'age': 20},
        {'name': 'Charlie', 'age': 30}
    ]
    sorted_people = sorted(people, key = lambda x: x['age'])
    print(sorted_people)
    
    这里使用了匿名函数lambda x: x['age']作为key参数的值。这个匿名函数接受一个字典作为参数,返回字典中age对应的值。sorted()函数根据这个返回值对people列表进行排序,输出结果为[{'name': 'Bob', 'age': 20}, {'name': 'Alice', 'age': 25}, {'name': 'Charlie', 'age': 30}],按照年龄从小到大对人员列表进行了排序。
  3. 对复数列表按照实部或虚部排序 对于复数列表,我们可以通过key参数自定义按照实部或虚部进行排序。例如,按照复数的实部进行排序,代码如下:
    complex_list = [3 + 4j, 1 + 2j, 5 + 1j]
    sorted_by_real = sorted(complex_list, key = lambda z: z.real)
    print(sorted_by_real)
    
    上述代码中,lambda z: z.real表示将复数的实部作为排序依据,sorted()函数会根据复数的实部从小到大对列表进行排序,输出结果为[(1+2j), (3+4j), (5+1j)]。如果要按照虚部排序,只需将key函数改为lambda z: z.imag即可。

四、稳定性排序

  1. 稳定性排序的概念 稳定性排序是指在排序过程中,相等元素的相对顺序保持不变。sorted()函数在Python中是稳定排序的。例如,有一个包含成绩和学生姓名的列表,成绩相同的学生希望保持原来的顺序,sorted()函数可以满足这个需求。
  2. 稳定性排序示例
    student_scores = [('Alice', 85), ('Bob', 90), ('Charlie', 85), ('David', 95)]
    sorted_students = sorted(student_scores, key = lambda x: x[1])
    print(sorted_students)
    
    在上述代码中,AliceCharlie的成绩都是85,经过sorted()函数排序后,Alice仍然在Charlie之前,保持了原来的相对顺序,体现了 sorted()函数的稳定性。

五、多关键字排序

  1. 结合operator.itemgetter进行多关键字排序 在实际应用中,有时需要根据多个关键字对列表进行排序。例如,对于前面提到的包含学生姓名和成绩的列表,我们希望先按照成绩从高到低排序,如果成绩相同,则按照姓名的字典序从小到大排序。可以借助operator模块中的itemgetter函数来实现。示例代码如下:
    from operator import itemgetter
    student_scores = [('Alice', 85), ('Bob', 90), ('Charlie', 85), ('David', 95)]
    sorted_students = sorted(student_scores, key = itemgetter(1, 0), reverse = True)
    print(sorted_students)
    
    这里itemgetter(1, 0)表示先根据索引1(即成绩)进行排序,如果成绩相同,再根据索引0(即姓名)进行排序。reverse = True表示整体按照从高到低的顺序排序。输出结果为[('David', 95), ('Bob', 90), ('Alice', 85), ('Charlie', 85)],满足了多关键字排序的需求。
  2. 使用functools.cmp_to_key实现自定义比较函数多关键字排序 除了itemgetter,还可以使用functools模块中的cmp_to_key函数来实现更复杂的自定义比较函数进行多关键字排序。cmp_to_key函数可以将传统的比较函数转换为key函数,供sorted()函数使用。例如,我们仍然对学生成绩列表进行排序,先按照成绩从高到低排序,如果成绩相同,再按照姓名长度从长到短排序。示例代码如下:
    from functools import cmp_to_key
    student_scores = [('Alice', 85), ('Bob', 90), ('Charlie', 85), ('David', 95)]
    def custom_cmp(a, b):
        if a[1]!= b[1]:
            return b[1] - a[1]
        else:
            return len(b[0]) - len(a[0])
    sorted_students = sorted(student_scores, key = cmp_to_key(custom_cmp))
    print(sorted_students)
    
    在上述代码中,custom_cmp函数定义了比较逻辑,先比较成绩,成绩不同时按照成绩从高到低排序;成绩相同时,比较姓名长度,按照姓名长度从长到短排序。cmp_to_key(custom_cmp)将这个比较函数转换为key函数供sorted()函数使用,最终实现了复杂的多关键字排序。

六、对嵌套列表排序

  1. 对二维列表按特定列排序 假设有一个二维列表,表示学生的学号、姓名和成绩,我们希望按照成绩对这个二维列表进行排序。示例代码如下:
    students = [
        [1, 'Alice', 85],
        [2, 'Bob', 90],
        [3, 'Charlie', 85]
    ]
    sorted_students = sorted(students, key = lambda x: x[2])
    print(sorted_students)
    
    在上述代码中,lambda x: x[2]表示根据二维列表中每个子列表的索引2(即成绩)进行排序,输出结果为[[1, 'Alice', 85], [3, 'Charlie', 85], [2, 'Bob', 90]],按照成绩从小到大对学生列表进行了排序。
  2. 对多层嵌套列表排序 对于更复杂的多层嵌套列表,同样可以利用key参数进行排序。例如,有一个列表,每个元素是一个包含班级和学生信息的元组,学生信息又是一个包含学号、姓名和成绩的列表,现在要按照学生成绩对整个列表进行排序。示例代码如下:
    classes = [
        ('Class1', [[1, 'Alice', 85], [2, 'Bob', 90]]),
        ('Class2', [[3, 'Charlie', 80], [4, 'David', 85]])
    ]
    def get_score(item):
        students = item[1]
        scores = [student[2] for student in students]
        return scores[0] if scores else 0
    sorted_classes = sorted(classes, key = get_score)
    print(sorted_classes)
    
    在上述代码中,get_score函数定义了如何从多层嵌套结构中获取学生成绩作为排序依据。sorted()函数根据这个函数的返回值对classes列表进行排序,实现了对多层嵌套列表按特定条件排序。

七、与其他数据结构结合使用时的排序灵活性

  1. 对集合转换为列表后排序 集合是Python中的一种无序数据结构,当我们需要对集合中的元素进行排序时,可以先将集合转换为列表,然后使用sorted()函数。例如:
    num_set = {5, 3, 8, 1, 9}
    num_list = list(num_set)
    sorted_num_list = sorted(num_list)
    print(sorted_num_list)
    
    上述代码先将集合num_set转换为列表num_list,然后对列表进行排序,输出结果为[1, 3, 5, 8, 9]。虽然集合本身无序,但通过转换为列表并使用sorted()函数,我们可以得到有序的元素序列。
  2. 对字典的键或值排序 对于字典,我们可以对其键或值进行排序。例如,对字典的键进行排序,代码如下:
    my_dict = {'c': 3, 'a': 1, 'b': 2}
    sorted_keys = sorted(my_dict.keys())
    print(sorted_keys)
    
    上述代码通过sorted(my_dict.keys())对字典my_dict的键进行排序,输出结果为['a', 'b', 'c']。如果要对字典的值进行排序,可以先获取值的列表,然后进行排序,示例代码如下:
    my_dict = {'c': 3, 'a': 1, 'b': 2}
    sorted_values = sorted(my_dict.values())
    print(sorted_values)
    
    输出结果为[1, 2, 3],实现了对字典值的排序。

八、性能考虑与优化

  1. 大数据集排序性能 当处理大数据集时,排序的性能变得尤为重要。虽然sorted()函数在大多数情况下表现良好,但对于非常大的列表,可能需要考虑性能优化。例如,可以使用外部排序算法(如果列表太大无法完全加载到内存中),或者利用并行计算的方式来加速排序过程。在Python中,可以借助multiprocessing模块来实现并行排序的部分逻辑,但这需要更复杂的代码实现。
  2. 选择合适的排序算法 Python的sorted()函数内部使用的是Timsort算法,这是一种自适应的、稳定的排序算法,它结合了归并排序和插入排序的优点,在大多数情况下性能都很出色。然而,在某些特定场景下,如果对稳定性没有要求,并且数据具有特定的分布特征,使用其他排序算法(如快速排序)可能会有更好的性能。但Python标准库中并没有直接提供替换sorted()函数内部排序算法的方法,通常需要自己实现排序函数来选择其他算法。不过,除非对性能有极高的要求并且经过详细的性能测试,一般情况下使用sorted()函数自带的Timsort算法就能满足需求。

通过以上对Python列表sorted排序灵活性的深入探讨,我们可以看到sorted()函数在各种不同场景下的强大功能和广泛适用性。无论是基本数据类型列表的常规排序,还是复杂数据结构和自定义排序规则的处理,sorted()函数都能胜任,为Python开发者在数据处理和算法实现中提供了极大的便利。