我是靠谱客的博主 醉熏蜻蜓,最近开发中收集的这篇文章主要介绍【干货】python sorted()函数详尽教程(附lambda函数教程)(上)【干货】python sorted()函数超详尽教程(附lambda函数教程)(上)(下篇还在赶工)0. 前言1. sorted()函数的介绍2. 如何解决多排序规则问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

【干货】python sorted()函数超详尽教程(附lambda函数教程)(上)(下篇还在赶工)

作者: MELATONIN_T
转载之前请私信:CSDN平台的用户 MELATONIN_T

目录

  • 【干货】python sorted()函数超详尽教程(附lambda函数教程)(上)(下篇还在赶工)
  • 0. 前言
  • 1. sorted()函数的介绍
    • 1.1 sorted()函数的作用
      • 1.1.0 概述
      • 1.1.1 sorted的排序规则
        • - 数字
        • - 字符串
        • - 布尔值
        • 小结
    • 1.2 sorted()函数的参数
      • 1.2.1 iterable 可迭代对象
        • - 当iterable是字典时
        • - 当iterable是一个嵌套的可迭代对象时
      • 1.2.2 reverse
      • 1.2.3 key
      • 小结
  • 2. 如何解决多排序规则问题
      • 2.1 什么是多排序规则问题?
      • 2.2 巧妙地使用元组来辅助排序
    • 小结

0. 前言

sorted()函数作为一个内置函数(built-in function),在python中的使用频率比较高。我相信,基本上所有的python程序员都懂得如何使用sorted()函数。但是,并不是所有python程序员都懂得如何把sorted()用得更pythonic,更优雅。

在本文中,我将带领大家从sorted()函数的基本开始,详细介绍sorted()函数的运用,包括如何使用lambda。

本教程将分上下两篇,上篇主要介绍sorted()函数的基本功能与如何解决多规则的排序问题。下篇则围绕着lambda函数展开。希望大家在看完本教程之后能有所收获。

在学习本教程之后,大家应该仅能利用一行代码解开以下问题:

# 排序问题 : 排序规则:奇数<偶数<小写字母<大写字母。奇偶数,大小写字母各自内部分别按照升序排列。
['A', 2, 3, 'g', 4, 1]

# 答案例:[1, 3, 2, 4, 'g', 'A']

那么,就让我们开始教程吧。


1. sorted()函数的介绍

1.1 sorted()函数的作用

1.1.0 概述

什么是sorted()函数? 它是用来干什么的?

用官方文档里的话来说:The sorted() function returns a sorted list from the items in an iterable. “sorted函数会返回一个排好顺序的可迭代对象的列表。”

用人话来说:我们给sorted一个可以排序(准确来说是迭代)的东西,sorted会把它排好序,变成列表还给你。

什么叫排好序? sorted中的排序规则有哪些呢?我们一起来看下一节。


1.1.1 sorted的排序规则

sorted()函数非常强大,可以给字符串,列表,元组,字典,集合等可迭代对象进行排序。

>>>sorted([2, 3, 1])
[1, 2, 3]

就像上面的例子一样,在默认的情况下,列表中的数字会按照从小到大的顺序被排序。这就是sorted的一种排序规则。

在这一节中,我将带着大家了解(基本)所有的python sorted()函数的排序规则。


- 数字

sorted()中数字的默认排序规则是升序排列

这里说的数字不仅是int整数型,也可以包含float。我们来看一个例子。

>>>nums = [2.6, 3, 1, 1/3, -1]
>>>sorted(nums)
[-1, 0.3333333333333333, 1, 2.6, 3]

可以看到,无论是整数,小数,负数,还是计算式, sorted函数都会默认地把他们(和计算式的结果)从小到大排序。


- 字符串

字符串也是可以被排序的,原因,一言以蔽之,因为它是可迭代对象,因为它可以被for…in…

就像这样:

s = "python"
for char in s:
    print(char)

# results
p
y
t
h
o
n

我们使用了for…in…打印了字符串中的每一个字母。
(为什么我会重点强调可迭代对象这个问题我会在 1.2 sorted()函数的参数 中讲解)

既然字符串可以被排序,那它一定有一个排序规则。没有规则,根本无法进行排序。比如"a"在"b"之前,"b"在"c"之前,就是一种排序规则。在sorted中,字符串是如何被排序的呢?

字符串的排序规则很直观,不是按照ascii码,sorted会按照英文的字母表和字母的大小写进行排序。例如:

a<b<c<d<…<z
A<a, B<b, …, Z<z

如上所示,字母表越前面的字母越小,越后面的字母越大。一个字母的大写小于他的小写。

这里提一个小问题:不同字母的大小写之间如何比较大小呢?

还不了解的同学可以执行一下下面的代码看看

print("A" < "g")
print("G" < "a")

结果是

True
True

这背后的原因是:字符串的排序规则是“所有的大写字母都小于小写字母”。用图片解释比较直观,就不多赘述了,请看下图:

lst1 = list("abcdefgABCDEFG")
print(sorted(lst1))

# result
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'a', 'b', 'c', 'd', 'e', 'f', 'g']

这个例子里,所有的大写字母都被sorted排到了小写字母之前,而大小写字母内部是按照字母表顺序进行排列的。

用两句话总结字符串的排序规则:“所有的大写字母都小于小写字母”,“大小写相同时按字母表排序”


- 布尔值

布尔值有且只有两种:True和False

True
False

虽然看起来不太可能,但布尔值其实也是可以比较大小的。这一令人吃惊的现象背后的原因在于布尔值对象是整数对象的子类。可以直观地理解为:

True == 1
False == 0

布尔值也可以被看作是整数的0和1。

Python官方文档如是说:

The two objects representing the values False and True are the only Boolean objects. The Boolean type is a subtype of plain integers, and Boolean values behave like the values 0 and 1.

废话少说,上代码解释:

print(False + True)
print(True + True)
print(False * True)
print(True * True)
print(True / True)
print(100 * True)
print("布尔值的举动就和整数的举动一样 False == 0, True == 1")

# results
1
2
0
1
1.0
100
布尔值的举动就和整数的举动一样 False == 0, True == 1

是不是感觉非常神奇?

所以如果我们让sorted给一串布尔值进行排序的话,结果就和一串0和1的排序没有差别。0在前,1在后;False在前,True在后

b = [True, False, True, False]
print(sorted(b))

# result
[False, False, True, True]

小结

在这一节中,我们讨论了sorted的排序规则。用三句话总结来说就是整数升序排列,字符串先大写后小写按照字母表,布尔值先False后True。

在下一节中,我们将着眼sorted函数的参数,解释为什么我在这一节强调了“可迭代对象”这个词,以及进一步地探索sorted()函数的妙用。


1.2 sorted()函数的参数

sorted()函数可以接受三个参数

  • iterable: 可迭代对象
  • reverse(optional): reverse == True 或 False, 接受布尔值,默认值False
  • key(optional): 接受函数,默认值None

写出来是这么个形式:

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

接下来我会详细介绍这三个形式参数。


1.2.1 iterable 可迭代对象

我在上一节中就提到过可迭代对象。可迭代对象的标志就是可以被for…in…语法从其中顺次拿到数据进行使用。用术语来说,一个可以被遍历的对象叫做可迭代对象。

其实有个更准确的定义,一个具备了__iter__方法的对象(或者说迭代器协议),就是一个可迭代对象。但鉴于本文的主题并不是可迭代对象,就不在此赘述了。感兴趣的小伙伴可以上百度或谷歌搜索iterable进行学习。

常见的可迭代对象有:list、tuple、dict、set、str等等。下面是对列表,元组,字符串分别使用sorted()函数的例子。
常见的可迭代对象
下面讲几种需要特殊注意的情况。


- 当iterable是字典时

当我们把字典作为iterable的实际参数传给sorted()函数时,返回值会是一个列表,这个列表的内容是这个字典排好序的键。

dic = {
    "Tom": "13",
    "Alice": "14",
    "Bob": "15",
    "alice": "16",
}
print(sorted(dic))

# result
['Alice', 'Bob', 'Tom', 'alice']

有趣的是,这个字典的键被按照首字母来排序了(Alice的A,Bob的B,Tom的T,最后是alice的a)。这个例子这正是我们下面要讲的可迭代对象的嵌套。可迭代对象的嵌套究竟是如何被sorted()函数排序的呢?我们一起来看下一小节。


- 当iterable是一个嵌套的可迭代对象时

嵌套的可迭代对象的简单例子:

{"": [], "": [],"":  []}
[(), (), ()]
([], [], [])

以上三个例子分别是:字典中嵌套列表,列表中嵌套元组,元组中嵌套列表。(省略了其中的元素)

嵌套的可迭代对象的比较是通过比较所有的,对应结构的嵌套最底层的第一个元素实现的。如果第一个元素一致,就会比较下一个元素。来看一个例子:

A = (1, 2 ,3)
B = (3, 1, 2)
C = ((2, 1), 3)
D = (2, (1, 3))
print(A < B)
print(B < D) # 注意不是 B < C

# result
True
False

注意!!!如果嵌套结构不一致的话会报错

A = (1, 2 ,3)
B = (3, 1, 2)
C = ((2, 1), 3)
D = (2, (1, 3))
print(B < C)

# result
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-599bb9711cb1> in <module>()
      3 C = ((2, 1), 3)
      4 D = (2, (1, 3))
----> 5 print(B < C)

TypeError: '<' not supported between instances of 'int' and 'tuple'

报错的原因是嵌套结构不一样导致了sorted把元组(2, 1)和整数2进行了比较。所以发生了TypeError: ‘<’ not supported between instances of ‘int’ and ‘tuple’

如果第一个元素一致,就会比较下一个元素:

A = (1, 1, 2)
B = (1, 2, 3)
print(A < B)

# result
True

再总结一下,嵌套的可迭代对象的比较是通过比较所有的,对应位置的最底层的第一个元素实现的。如果第一个元素一致,就会比较下一个元素,一直到分出大小为止。


1.2.2 reverse

reverse这个形式参数接受布尔值,它的默认值是False。

我们用一个例子来比较一下reverse == False 和 reverse == True 时sorted()函数的行为:

reverse == False 和 reverse == True 时sorted()函数的行为

如图所示,我们将列表lst = [2, 3, 1, 4, 5]传给函数sorted。

当reverse == False或者不输入的时候,返回的结果是[1, 2, 3, 4, 5];当reverse == True的时候,返回的结果是[5, 4, 3, 2, 1]

reverse == True会让sorted()函数的排序规则反过来。

reverse = False(默认)的排序规则:

整数升序排列,字符串先大写后小写按照字母表,布尔值先False后True。

而当reverse == True时,排序规则就变成了:

整数降序排列,字符串先小写后大写按照反过来的字母表,布尔值先True后False。


1.2.3 key

在key中可以输入自己声明的函数或者Python内置的函数作为排序的标准。

使用Python内置函数的例子:

# 在sorted中使用python自带的函数/方法
# 转载之前请私信:CSDN平台的用户 MELATONIN_T
lst = ['4345' ,'d', '24', 'b', '3', 'c']
sorted_lst_isdigit = sorted(lst, key = str.isdigit)
sorted_lst_len = sorted(lst, key = len)
print("sorted_lst_isdigit: ", sorted_lst_isdigit)
print("sorted_lst_len: ", sorted_lst_len)

# results
sorted_lst_isdigit:  ['d', 'b', 'c', '4345', '24', '3']
sorted_lst_len:  ['d', 'b', '3', 'c', '24', '4345']

在这个例子中,我们分别传给sorted() .isdigit()方法和len()函数。

key == str.isdigit时,按照是否为数字排序。返回的元组字母在前(False),数字在后(True)

key == len时,按照字符串长度排序。字符串越长,排在越后面。长度相同时按照原来的顺序排。(而不是按照字母表或者数字大小排。因为我们自定义了排序规则,所以sorted将不按照默认规则进行排序。)

自己声明函数的例子:
在sorted中使用自己的函数
在这个例子中,我们声明了函数sort_with_second_num;旨在以每个元组中的第二个元素的大小作为排序规则。

实际输出的结果[(3, 1), (1, 2), (2, 3)]确实遵守了这个规则。


小结

在这一小节中,我们讨论了sorted()函数的三个参数;测试了sorted()函数在iterable是不同形式时的不同表现;在最后学习了如何使用Python内置函数和自己定义的函数作为排序的key。

在下一节中,我们将学习如何应对拥有两个或两个以上排序规则的排序问题。


2. 如何解决多排序规则问题

在这一节中,我们将学习如何应对拥有两个或两个以上排序规则的排序问题。比起我们方才学习的排序问题(比如按照每个元组中的第二个元素的大小作为排序规则),这一类型的问题在实际操作中更加常见。

在学习完这一节后,我们应该能轻松面对如下问题:

# 元素:(学生名字, 学生成绩,学生年龄)
# 要求成绩从低到高,成绩一样的按照年龄从小到大排
students_list = [
    ("Alice", 90, 18),
    ("Peter", 75, 20),
    ("Bob", 90, 20),
    ("Jane", 80, 19),
    ("Jack", 80, 21),
]

# answer
[('Peter', 75, 20), ('Jane', 80, 19), ('Jack', 80, 21), ('Alice', 90, 18), ('Bob', 90, 20)]

2.1 什么是多排序规则问题?

有时候我们需进行排序操作的对象的规则不止一个。

例如:小红想要谈朋友,开出的第一个条件是男方的身高,越高越好,3米最好(打个比方而已);如果有身高一样的男同胞就按照月收入来排序,月收高的优先。

虽然很现实很残酷,小红将会一个男朋友也没有,孤寡一生,但这恰恰就是一个有两个规则的排序问题的很好的例子。在这个例子中我们需要两个key:1.身高 2.月收。

为此我们需要在参数key中做一些文章。

2.2 巧妙地使用元组来辅助排序

为了更好地理解如何使用元组来辅助我们解决问题,我们再来温习一下元组的排序规则。

>>>(1, 2) < (1, 3)
True
>>>(1, 2) < (2, 2)
True
>>>(1, 2, 3)< (3, 4)
True

一图胜千言。

处理多排序规则问题的关键就在于让我们传给key的函数返回一个元组 — 然后我们利用这个元组进行排序。

小红的问题中,我们要让key中的函数返回

(身高, 月收)

结果传给sorted()之后,sorted()会先比较元组中的第一个元素“身高”,如果身高一样,就会比较月收。程序如下

def sorter(males: list):
    height = males[0]
    salary = males[1]
    return (height, salary) # 让函数返回(身高, 月收)

# 可供小红选择的对象
tom = [160, 50000, "汤姆"]
jack = [180, 3000, "杰克"]
gaofushuai = [180, 50000, "高富帅"]
males = [tom, jack, gaofushuai]

# key = sorter,让sorted用元组(身高, 月收)排序
sorted_males = sorted(males, key = sorter)

print(sorted_males)
print(f"最终小红选择了{sorted_males[2][2]}")


#result
[[160, 50000, '汤姆'], [180, 3000, '杰克'], [180, 50000, '高富帅']]
最终小红选择了高富帅

值得注意的是,我们在def sorter(males):这一行里给sorter传的参数是一个列表。

这是因为sorter会顺次的访问被排序对象中的每一个元素(这个例子是写有每一位男方信息的列表),然后把它传给key。


这节开头的问题同学们会解答了吗?

我会把答案贴在下面(仅作参考)

# 元素:(学生名字, 学生成绩,学生年龄)
# 要求成绩从低到高,成绩一样的按照年龄从小到大排
students_list = [
    ("Alice", 90, 18),
    ("Peter", 75, 20),
    ("Bob", 90, 20),
    ("Jane", 80, 19),
    ("Jack", 80, 21),
]

# answer
[('Peter', 75, 20), ('Jane', 80, 19), ('Jack', 80, 21), ('Alice', 90, 18), ('Bob', 90, 20)]

在这里插入图片描述


小结

在这一节中,我们学习了如何应对拥有两个或两个以上排序规则的排序问题。

在接下来的python sorted()函数详尽教程(下)中,我们将接触lambda匿名函数,并了解如何在在sorted()中使用lambda来解决实际问题。


  1. lambda匿名函数的介绍

  2. 在sorted()中使用lambda

让我们下篇再见!(还在赶工中)

最后

以上就是醉熏蜻蜓为你收集整理的【干货】python sorted()函数详尽教程(附lambda函数教程)(上)【干货】python sorted()函数超详尽教程(附lambda函数教程)(上)(下篇还在赶工)0. 前言1. sorted()函数的介绍2. 如何解决多排序规则问题的全部内容,希望文章能够帮你解决【干货】python sorted()函数详尽教程(附lambda函数教程)(上)【干货】python sorted()函数超详尽教程(附lambda函数教程)(上)(下篇还在赶工)0. 前言1. sorted()函数的介绍2. 如何解决多排序规则问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部