Python 内建函数 - sorted(iterable[, key][, reverse])

Manual

Return a new sorted list from the items in iterable.

Has two optional arguments which must be specified as keyword arguments.

key specifies a function of one argument that is used to extract a comparison key from each list element: key=str.lower. The default value is None (compare the elements directly).

reverse is a boolean value. If set to True, then the list elements are sorted as if each comparison were reversed.

Use functools.cmp_to_key() to convert an old-style cmp function to a key function.

The built-in sorted() function is guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal — this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade).

For sorting examples and a brief sorting tutorial, see Sorting HOW TO.

直译

根据iterable中的项返回一个新排序的列表。

这里有两个可选参数,其必须指定为关键字参数。

  • key指定某个参数的函数,它可以用于从每个列表元素中提取比较键,例如key=str.lower。默认值为None(直接比较元素)。
  • reverse是一个布尔值,如果设置为True,列表的元素会将每个比较反置进行排列。

内建sorted()函数可以保证稳定,如果它保证不改变元素的相对顺序,那么排序就是稳定的。相对顺序的比较恒等,对于多次传递下的排序很有用(例如:按部门排序,然后按工资等级排序)

实例

实例摘自官方手册

基本排序

# 简单排序
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
# list.sort()方法,该方法仅对列表定义。
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
# sorted()支持任何迭代形式
>>> sorted({
  1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
 
 

    key函数

    list.sort()和sorted()都有key参数,用来指定一个函数,并对每个列表元素对象调用该函数进行比较。

    # 小写字符串比较,key=str.lower
    >>> sorted("This is a test string from Andrew".split(), key=str.lower)
    ['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
     
     

      key参数的值应该是一个函数,其获取一个单独的参数,并返回一个用于排序目的键。这个技术执行速度快,因为每个输入记录只调用一次key函数。

      常见模式式排序复杂对象,会使用一些对象的索引作为键,例如:

      >>>
      >>> student_tuples = [
      ...     ('john', 'A', 15),
      ...     ('jane', 'B', 12),
      ...     ('dave', 'B', 10),
      ... ]
      >>> sorted(student_tuples, key=lambda student: student[2])   
      # 依照年龄排序
      [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
       
       

        对于有已命名属性的对象,可以使用相同的技术,例如:

        >>>
        >>> 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))
        >>>
        >>> student_objects = [
        ...     Student('john', 'A', 15),
        ...     Student('jane', 'B', 12),
        ...     Student('dave', 'B', 10),
        ... ]
        >>> sorted(student_objects, key=lambda student: student.age)   
        # 依照年龄排序
        [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
         
         

          operator模块函数

          上面展示的是很常见的key函数模式,因此Python提供了便捷的函数来使访问器函数更简单、更迅速,operator模块有itemgetter()attrgetter()methodcaller()函数。

          使用这些函数,上面的实例可以变得更简单快速:

          >>>
          >>> from operator import itemgetter, attrgetter
          >>>
          >>> sorted(student_tuples, key=itemgetter(2))
          [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
          >>>
          >>> sorted(student_objects, key=attrgetter('age'))
          [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
           
           

            operator模块函数允许多层级排序,例如,先按等级排序,然后按年龄:

            >>>
            >>> sorted(student_tuples, key=itemgetter(1,2))
            [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
            >>>
            >>> sorted(student_objects, key=attrgetter('grade', 'age'))
            [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
             
             

              升序和降序

              list.sort()和sorted()都接受reverse参数(布尔值),这用于标识降序排序,例如:以反向年龄顺序获取学生数据:

              >>>
              >>> sorted(student_tuples, key=itemgetter(2), reverse=True)
              [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
              >>>
              >>> sorted(student_objects, key=attrgetter('age'), reverse=True)
              [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
               
               

                排序稳定性和复杂排序

                排序可以保证稳定性,这意味着如果多个记录具有相同的键,它们原来的顺序是受保护的。

                >>>
                >>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
                >>> sorted(data, key=itemgetter(0))
                [('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
                 
                 

                  注意两条blue记录保持了它们原有的顺序,即(‘blue’, 1) 是确保在(‘blue’, 2)之前的。

                  这条神奇的属性可以让你在一系列的排序级内建立复杂排序,例如:以年级降序排列学生数据,然后升序排列年龄。因此先做年龄排序,然后再使用年级排序:

                  >>>
                  >>> s = sorted(student_objects, key=attrgetter('age'))     
                  # 以第二个键排序
                  >>> sorted(s, key=attrgetter('grade'), reverse=True)       
                  # 现在以第一个键降序排序
                  [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
                   
                   

                    Python的多重排序使用了Timsort算法,感兴趣的同学可以自行查找资料。

                    其他

                    • 对于本地化识别的排序,为key函数使用locale.strxfrm(),或为比较函数使用locale.strcoll()
                    • reverse参数仍然可以保持排序的稳定性(因此同等键的记录可以保持原始顺序)。有趣的是,可以通过使用内建reversed()函数两次来模拟这个效果:
                    >>>
                    >>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
                    >>> standard_way = sorted(data, key=itemgetter(0), reverse=True)
                    >>> double_reversed = list(reversed(sorted(reversed(data), key=itemgetter(0))))
                    >>> assert standard_way == double_reversed
                    >>> standard_way
                    [('red', 1), ('red', 2), ('blue', 1), ('blue', 2)]
                     
                     
                      • 当在两个对象间进行比较时,排序程序会使用\ lt(),因此定义一个\ lt()方法将一个标准排列顺序添加到类中,会使排序变得简单:
                      >>>
                      >>> Student.__lt__ = lambda self, other: self.age < other.age
                      >>> sorted(student_objects)
                      [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
                       
                       
                        • Key函数不需要直接依赖排序的对象,它也可以访问外部资源。例如:如果对字典中学生年级排序,它们可以用分离的学生名列表排列。
                        >>>
                        >>> students = ['dave', 'john', 'jane']
                        >>> newgrades = {
                          'john': 'F', 'jane':'A', 'dave': 'C'}
                        >>> sorted(students, key=newgrades.__getitem__)
                        ['jane', 'dave', 'john']
                         

                        拓展阅读

                        operator
                        itemgetter()
                        attrgetter()
                        methodcaller()
                        locale.strxfrm()
                        locale.strcoll()
                        reversed()

                        上一篇:js函数组合


                        下一篇:CV之FC:计算机视觉之人脸识别(Face Recognition)方向的简介、代码实现、案例应用之详细攻略(二)