Python教程

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

本文主要是介绍Python 内建函数 - sorted(iterable[, key][, reverse]),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
  • Manual
  • 直译
  • 实例
    • 基本排序
    • key函数
    • operator模块函数
    • 升序和降序
    • 排序稳定性和复杂排序
  • 其他
  • 拓展阅读

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()

这篇关于Python 内建函数 - sorted(iterable[, key][, reverse])的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!