Python sorted()函数

原文: https://thepythonguru.com/python-builtin-functions/sorted/


于 2020 年 1 月 7 日更新


sorted()内置函数允许我们对数据进行排序。 它接受一个可迭代对象,并返回一个包含来自可迭代对象的项目的排序列表。 默认情况下,它以升序排序。

sorted()函数的语法如下:

语法sorted(iterable, key=None, reverse=False)

参数 描述
iterable (必需)可迭代地进行排序,例如字符串,列表,字典,元组等。
key,(可选) 它引用单个参数函数以自定义排序顺序。 该函数应用于迭代器上的每个项目。 默认情况下,此参数设置为None
reverse (可选)布尔值标志以反转排序顺序。 默认为False

如果可迭代对象中的项目是字符串,则将按字母顺序对其进行排序。 另一方面,如果它们是数字,则将按数字顺序对其进行排序。

这是一个例子:

  1. >>>
  2. >>> fruits = ['lime', 'blueberry', 'plum', 'avocado']
  3. >>>
  4. >>> sorted(fruits) # default sorting, in ascending order
  5. ['avocado', 'blueberry', 'lime', 'plum']
  6. >>>
  7. >>>
  8. >>> sorted(fruits, reverse=True) # reverse the sorting
  9. ['plum', 'lime', 'blueberry', 'avocado']
  10. >>>
  11. >>>
  12. >>> ages = [45, 11, 30, 20, 55]
  13. >>>
  14. >>> sorted(ages)
  15. [11, 20, 30, 45, 55]
  16. >>>
  17. >>> sorted(ages, reverse=True)
  18. [55, 45, 30, 20, 11]
  19. >>>

试试看:

  1. fruits = ['lime', 'blueberry', 'plum', 'avocado']
  2. print(sorted(fruits)) # default sorting, in ascending order
  3. print(sorted(fruits, reverse=True)) # reverse the sorting
  4. ages = [45, 11, 30, 20, 55]
  5. print(sorted(ages))
  6. print(sorted(ages, reverse=True))

请注意,sorted()返回一个包含可迭代项的新列表。 它不会更改过程中的原始可迭代项。

  1. >>>
  2. >>> fruits # fruit list is same as before
  3. ['lime', 'blueberry', 'plum', 'avocado']
  4. >>>
  5. >>>
  6. >>> ages # ages list is same as before
  7. [45, 11, 30, 20, 55]
  8. >>>

试一试:

  1. fruits = ['lime', 'blueberry', 'plum', 'avocado']
  2. ages = [45, 11, 30, 20, 55]
  3. print(sorted(fruits)) # default sorting, in ascending order
  4. print(sorted(fruits, reverse=True)) # reverse the sorting
  5. print(fruits)
  6. print(ages)

以下是一些其他示例,显示sorted()如何与其他 Python 类型一起使用。

带字符串的sorted()


  1. >>>
  2. >>> name = "Alfred Hajos"
  3. >>>
  4. >>> sorted(name)
  5. [' ', 'A', 'H', 'a', 'd', 'e', 'f', 'j', 'l', 'o', 'r', 's']
  6. >>>
  7. >>>
  8. >>> sorted(name, reverse=True)
  9. ['s', 'r', 'o', 'l', 'j', 'f', 'e', 'd', 'a', 'H', 'A', ' ']
  10. >>>

试一试:

  1. name = "Alfred Hajos"
  2. print(sorted(name))
  3. print(sorted(name, reverse=True))

请注意,在第一个sorted()调用A的结果出现在a之前。 这是因为A的 ASCII 值为 65,a的 ASCII 值为 97。出于相同的原因,空格字符(' ')的 ASCII 值 32 出现在A之前。

带元组的sorted()


  1. >>>
  2. >>> t = ( 'ff', 'xx', 'gg', 'aa')
  3. >>>
  4. >>> sorted(t)
  5. ['aa', 'ff', 'gg', 'xx']
  6. >>>
  7. >>> sorted(t, reverse=True)
  8. ['xx', 'gg', 'ff', 'aa']
  9. >>>

试一试:

  1. t = ( 'ff', 'xx', 'gg', 'aa')
  2. print(sorted(t))
  3. print(sorted(t, reverse=True))

带字典的sorted()


  1. >>>
  2. >>> d = {'name': 'John', 'age': 25, 'designation': 'manager'}
  3. >>>
  4. >>>
  5. >>> sorted(d)
  6. ['age', 'designation', 'name']
  7. >>>
  8. >>> sorted(d, reverse=True)
  9. ['name', 'designation', 'age']
  10. >>>
  11. >>>
  12. >>> for k in sorted(d):
  13. ... print(k, d[k])
  14. ...
  15. age 25
  16. designation manager
  17. name John
  18. >>>
  19. >>>
  20. >>> for k in sorted(d, reverse=True):
  21. ... print(k, d[k])
  22. ...
  23. name John
  24. designation manager
  25. age 25
  26. >>>
  1. d = {'name': 'John', 'age': 25, 'designation': 'manager'}
  2. print(sorted(d))
  3. print(sorted(d, reverse=True))
  4. for k in sorted(d):
  5. print(k, d[k])
  6. print('-'*10)
  7. for k in sorted(d, reverse=True):
  8. print(k, d[k])

使用命名参数key自定义排序顺序


从上一节中我们知道,如果将sorted()函数应用于字符串列表,则将获得按字母顺序排序的字符串列表。

如果我们想按字符串的长度而不是字母顺序排序怎么办?

这是key命名参数出现的地方。

要按字符串长度排序,请按以下所示将len()函数的键命名参数设置为:

  1. >>>
  2. >>> fruits
  3. ['lime', 'blueberry', 'plum', 'avocado']
  4. >>>
  5. >>> sorted(fruits) # sort by alphabetical order
  6. ['avocado', 'blueberry', 'lime', 'plum']
  7. >>>
  8. >>> sorted(fruits, key=len) # sort by string length
  9. ['lime', 'plum', 'avocado', 'blueberry']
  10. >>>
  11. >>> sorted(fruits, key=len, reverse=True) # reverse sort order
  12. ['blueberry', 'avocado', 'lime', 'plum']
  13. >>>

试一试:

  1. fruits = ['lime', 'blueberry', 'plum', 'avocado']
  2. print(fruits)
  3. print(sorted(fruits))
  4. print(sorted(fruits, key=len)) # sort by string length
  5. print(sorted(fruits, key=len, reverse=True)) # reverse sort order

有时您可能希望使排序不区分大小写。 我们可以通过将key的命名参数设置为str.lower函数来轻松实现此目的。

  1. >>>
  2. >>> t = ( 'AA', 'aa', 'ZZ', 'cc', 'bb')
  3. >>>
  4. >>> sorted(t)
  5. ['AA', 'ZZ', 'aa', 'bb', 'cc']
  6. >>>
  7. >>> sorted(t, key=str.lower)
  8. ['AA', 'aa', 'bb', 'cc', 'ZZ']
  9. >>>
  1. t = ( 'AA', 'aa', 'ZZ', 'cc', 'bb')
  2. print(sorted(t))
  3. print(sorted(t, key=str.lower))

这是另一个示例,该示例使用自定义函数根据其包含的元音数量对字符串列表进行排序。

  1. >>>
  2. >>> fruits
  3. ['lime', 'blueberry', 'plum', 'avocado']
  4. >>>
  5. >>>
  6. >>> def count_vowel(s):
  7. ... vowels = ('a', 'e', 'i', 'o', 'u')
  8. ... count = 0
  9. ...
  10. ... for i in s:
  11. ... if i in vowels:
  12. ... count = count + 1
  13. ...
  14. ... return count
  15. ...
  16. >>>
  17. >>>
  18. >>> sorted(fruits)
  19. ['avocado', 'blueberry', 'lime', 'plum']
  20. >>>
  21. >>> sorted(fruits, key=count_vowel)
  22. ['plum', 'lime', 'blueberry', 'avocado']
  23. >>>

试一试:

  1. fruits = ['lime', 'blueberry', 'plum', 'avocado']
  2. def count_vowel(s):
  3. vowels = ('a', 'e', 'i', 'o', 'u')
  4. count = 0
  5. for i in s:
  6. if i in vowels:
  7. count = count + 1
  8. return count
  9. print(sorted(fruits))
  10. print(sorted(fruits, key=count_vowel))

您还可以在用户定义的对象上使用sorted()

  1. >>>
  2. >>> class Employee:
  3. ... def __init__(self, name, salary, age):
  4. ... self.name = name
  5. ... self.salary = salary
  6. ... self.age = age
  7. ...
  8. ... def __repr__(self):
  9. ... return self.__str__()
  10. ...
  11. ... def __str__(self):
  12. ... return "{0}:{1}:{2}".format(self.name, self.salary, self.age)
  13. ...
  14. >>>
  15. >>>
  16. >>> e1 = Employee("Tom", 20000, 32)
  17. >>> e2 = Employee("Jane", 50000, 36)
  18. >>> e3 = Employee("Bob", 45000, 40)
  19. >>>
  20. >>>
  21. >>> emp_list = [e2, e3, e1]
  22. >>>
  23. >>> print(emp_list)
  24. [Jane:50000:36, Bob:45000:40, Tom:20000:32]
  25. >>>
  1. class Employee:
  2. def __init__(self, name, salary, age):
  3. self.name = name
  4. self.salary = salary
  5. self.age = age
  6. def __repr__(self):
  7. return self.__str__()
  8. def __str__(self):
  9. return "{0}:{1}:{2}".format(self.name, self.salary, self.age)
  10. e1 = Employee("Tom", 20000, 32)
  11. e2 = Employee("Jane", 50000, 36)
  12. e3 = Employee("Bob", 45000, 40)
  13. emp_list = [e2, e3, e1]
  14. print(emp_list)
  15. # print(sorted(emp_list))

如果现在在emp_list上调用sorted(),则会出现如下错误:

  1. >>>
  2. >>> sorted(emp_list)
  3. Traceback (most recent call last):
  4. File "<stdin>", line 1, in <module>
  5. TypeError: unorderable types: Employee() < Employee()
  6. >>>

提示

上面的代码不会在 Python 2 中引发任何错误。相反,它将根据id()内置函数返回的 ID 对Employee对象进行排序。

发生这种情况是因为 Python 不知道如何比较Employee对象。 我们可以通过在Employee类中实现特殊方法(例如__lt__()__gt__()等)来告诉 Python 如何比较对象。

代替定义特殊方法,我们可以显式告诉sorted()函数如何使用key命名参数对Employee对象进行排序。

  1. >>>
  2. >>> sorted(emp_list, key=lambda x: x.name) # sort Employee objects by name
  3. [Bob:45000:40, Jane:50000:36, Tom:20000:32]
  4. >>>
  5. >>>
  6. >>> sorted(emp_list, key=lambda x: x.age) # sort Employee objects by age
  7. [Tom:20000:32, Jane:50000:36, Bob:45000:40]
  8. >>>
  9. >>>
  10. >>> print(sorted(emp_list, key=lambda x: x.salary)) # sort Employee objects by salary
  11. [Tom:20000:32, Bob:45000:40, Jane:50000:36]
  12. >>>
  1. class Employee:
  2. def __init__(self, name, salary, age):
  3. self.name = name
  4. self.salary = salary
  5. self.age = age
  6. def __repr__(self):
  7. return self.__str__()
  8. def __str__(self):
  9. return "{0}:{1}:{2}".format(self.name, self.salary, self.age)
  10. e1 = Employee("Tom", 20000, 32)
  11. e2 = Employee("Jane", 50000, 36)
  12. e3 = Employee("Bob", 45000, 40)
  13. emp_list = [e2, e3, e1]
  14. print(sorted(emp_list, key=lambda x: x.name)) # sort Employee objects by name
  15. print(sorted(emp_list, key=lambda x: x.age)) # sort Employee objects by age
  16. print(sorted(emp_list, key=lambda x: x.salary)) # sort Employee objects by salary