sorted(key=lambda: ...) 背后的语法[重复]
- 2025-01-16 08:38:00
- admin 原创
- 122
问题描述:
我不太明白这个sorted()
论点背后的语法:
key=lambda variable: variable[0]
这不是lambda
任意的吗?为什么variable
在看起来像 的地方两次提到dict
?
解决方案 1:
我认为这里的所有答案都很好地涵盖了 lambda 函数在上下文中所做的核心内容sorted()
,但我仍然觉得缺乏能够让人直观理解的描述,所以这里是我的看法。
为了完整起见,我将首先说明显而易见的事情:sorted()
返回已排序元素的列表,如果我们想以特定方式排序,或者如果我们想对复杂的元素列表(例如嵌套列表或元组列表)进行排序,我们可以调用关键参数。
对我来说,对关键参数的直观理解、为什么它必须是可调用的以及使用 lambda 作为(匿名)可调用函数来实现这一点分为两部分。
使用 lambda 最终意味着您不必编写(定义)整个函数。Lambda 函数被创建、使用并立即销毁 - 因此它们不会用只会使用一次的代码来破坏您的代码。据我所知,这是 lambda 函数的核心实用性,其在此类角色中的应用非常广泛。它的语法纯粹是一种约定,本质上是一般编程语法的性质。学习语法并掌握它。
Lambda 语法如下:
lambda input_variable(s): tasty one liner
其中lambda
是 python 关键字。
例如
In [1]: f00 = lambda x: x/2
In [2]: f00(10)
Out[2]: 5.0
In [3]: (lambda x: x/2)(10)
Out[3]: 5.0
In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0
In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
该参数背后的想法
key
是,它应该采用一组指令,这些指令本质上将“sorted()”函数指向应该用于排序的列表元素。当它说时key=
,它真正的意思是:当我遍历列表时,一次一个元素(即for e in some_list
),我将把当前元素传递给 key 参数指定的函数,并使用它来创建一个转换后的列表,该列表将通知我最终排序列表的顺序。
一探究竟:
In [6]: mylist = [3, 6, 3, 2, 4, 8, 23] # an example list
# sorted(mylist, key=HowToSort) # what we will be doing
基本示例:
# mylist = [3, 6, 3, 2, 4, 8, 23]
In [7]: sorted(mylist)
Out[7]: [2, 3, 3, 4, 6, 8, 23]
# all numbers are in ascending order (i.e.from low to high).
示例 1:
# mylist = [3, 6, 3, 2, 4, 8, 23]
In [8]: sorted(mylist, key=lambda x: x % 2 == 0)
# Quick Tip: The % operator returns the *remainder* of a division
# operation. So the key lambda function here is saying "return True
# if x divided by 2 leaves a remainer of 0, else False". This is a
# typical way to check if a number is even or odd.
Out[8]: [3, 3, 23, 6, 2, 4, 8]
# Does this sorted result make intuitive sense to you?
请注意,我的 lambda 函数要求在排序之前sorted
检查每个元素e
是偶数还是奇数。
但请稍等!您可能(或可能应该)想知道两件事。
首先,为什么奇数排在偶数之前?毕竟,键值似乎是通过使用中的运算符来告诉sorted
函数优先考虑偶数。mod
`x % 2 == 0`
第二,为什么偶数仍然乱序?2 在 6 之前,对吗?
通过分析这个结果,我们将更深入地了解“key”参数的实际工作原理,尤其是与匿名 lambda 函数结合使用时。
首先,你会注意到,虽然奇数排在偶数之前,但偶数本身并没有排序。这是为什么呢?让我们阅读文档:
关键函数从 Python 2.4 开始,list.sort() 和 sorted() 都添加了一个关键参数,以指定在进行比较之前在每个列表元素上调用的函数。
我们必须在这里进行一点字里行间的解读,但是这告诉我们,sort函数只被调用一次,如果我们指定key参数,那么我们将按照key函数指向的值进行排序。
那么使用模数的示例会返回什么呢?一个布尔值:True == 1
,False == 0
。那么 sorted 如何处理这个键呢?它基本上将原始列表转换为 1 和 0 的序列。
[3, 6, 3, 2, 4, 8, 23]
变成[0, 1, 0, 1, 1, 1, 0]
现在我们有点进展了。对转换后的列表进行排序后会得到什么?
[0, 0, 0, 1, 1, 1, 1]
好的,现在我们知道了为什么奇数排在偶数之前。但下一个问题是:为什么在我的最终列表中 6 仍然排在 2 之前?这很简单 - 这是因为排序只发生一次!那些 1 仍然代表原始列表值,它们相对于彼此处于原始位置。由于排序只发生一次,并且我们不调用任何类型的排序函数来将原始偶数从低到高排序,因此这些值相对于彼此仍保持原始顺序。
最后一个问题是:当我打印出最终排序列表时,我该如何从概念上思考布尔值的顺序如何转换回原始值?
Sorted()
是一种内置方法(有趣的事实)使用一种名为Timsort 的混合排序算法,该算法结合了合并排序和插入排序的各个方面。在我看来,当您调用它时,有一个机制将这些值保存在内存中,并将它们与由lambda 函数确定的布尔身份(掩码)捆绑在一起。顺序由从 lambda 函数计算出的布尔身份决定,但请记住,这些子列表(一和零)本身并非按其原始值排序。因此,最终列表虽然按奇数和偶数组织,但不按子列表排序(在这种情况下偶数是无序的)。奇数有序是因为它们在原始列表中已经巧合地按顺序排列。从这一切中可以得出的结论是,当 lambda 进行这种转换时,子列表的原始顺序将保留。
那么,这一切与最初的问题有何关联?更重要的是,我们对如何sorted()
使用其关键参数和 lambda 来实现的直觉是什么?
该 lambda 函数可以被认为是一个指向我们需要排序的值的指针,无论它是将值映射到由 lambda 函数转换的布尔值的指针,还是嵌套列表、元组、字典等中的特定元素,同样由 lambda 函数确定。
让我们尝试预测当我运行以下代码时会发生什么。
In [9]: mylist = [(3, 5, 8), (6, 2, 8), (2, 9, 4), (6, 8, 5)]
In[10]: sorted(mylist, key=lambda x: x[1])
我的sorted
调用显然是说“请对此列表进行排序”。关键参数通过以下方式使其更加具体:对于x
中的每个元素mylist
,返回该元素的第二个索引,然后mylist
按照 lambda 函数计算的列表排序顺序对原始列表的所有元素进行排序。由于我们有一个元组列表,因此我们可以使用 lambda 函数从该元组中返回一个索引元素。
用于排序的指针是:
[5, 2, 9, 8] # the second element of each tuple
对此指针列表进行排序将返回:
[2, 5, 8, 9]
将其应用到mylist
,我们得到:
Out[10]: [(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]
# Notice the sorted pointer list is the same as the second index of each tuple in this final list
运行该代码,你会发现顺序就是这样的。尝试使用此关键函数对整数列表进行排序,你会发现代码会中断(为什么?当然,因为你无法索引整数)。
这是一个冗长的解释,但我希望这有助于sort
您直观地了解函数的使用lambda
——作为中的关键参数sorted()
,以及超越。
解决方案 2:
key
是一个函数,将在比较集合项之前调用该函数来转换集合项。传递给的参数key
必须是可调用的。
使用lambda
创建一个匿名函数(可调用)。在sorted
可调用的情况下,它只接受一个参数。Python 的函数lambda
非常简单。它实际上只能执行和返回一件事。
的语法lambda
是单词lambda
后跟参数名称列表,然后是单个代码块。参数列表和代码块用冒号分隔。这与 Python 中的其他构造类似,例如、while
等等。它们都是通常带有代码块的语句。Lambda 只是带有代码块的语句的另一个实例。for
`if`
我们可以比较 lambda 与 def 的用法来创建函数。
adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2
lambda 只是为我们提供了一种无需指定名称即可完成此操作的方法。这使得它非常适合用作函数的参数。
variable
这里使用了两次,因为在冒号的左边它是一个参数的名称,而在冒号的右边它在代码块中用于计算某些东西。
解决方案 3:
lambda
是一个 Python 关键字,用于生成匿名函数。
>>> (lambda x: x+2)(3)
5
解决方案 4:
左边variable
的:
是参数名,variable
右边的用法是使用该参数。
含义几乎完全相同:
def some_method(variable):
return variable[0]
解决方案 5:
另一个使用key=lambda 的sorted()函数的示例。假设您有一个元组列表。每个元组中都有汽车的品牌、型号和重量,并且您想按品牌、型号或重量对该元组列表进行排序。您可以使用 lambda 来做到这一点。
cars = [('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000), ('bmw', 'x5', 1700)]
print(sorted(cars, key=lambda car: car[0]))
print(sorted(cars, key=lambda car: car[1]))
print(sorted(cars, key=lambda car: car[2]))
结果:
[('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000)]
[('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100)]
[('citroen', 'xsara', 1100), ('bmw', 'x5', 1700), ('lincoln', 'navigator', 2000)]
解决方案 6:
简单且不耗时的答案,并附上与问题相关的例子,
请遵循此示例:
user = [{"name": "Dough", "age": 55},
{"name": "Ben", "age": 44},
{"name": "Citrus", "age": 33},
{"name": "Abdullah", "age":22},
]
print(sorted(user, key=lambda el: el["name"]))
print(sorted(user, key= lambda y: y["age"]))
看看名单上的名字,它们以 D、B、C 和 A 开头。如果你注意年龄,你会发现他们的年龄分别是 55、44、33 和 22。第一个印刷代码
print(sorted(user, key=lambda el: el["name"]))
结果为:
[{'name': 'Abdullah', 'age': 22},
{'name': 'Ben', 'age': 44},
{'name': 'Citrus', 'age': 33},
{'name': 'Dough', 'age': 55}]
对名称进行排序,因为通过 key=lambda el: el["name"] 我们对名称进行排序,并且名称按字母顺序返回。
第二次打印代码
print(sorted(user, key= lambda y: y["age"]))
结果:
[{'name': 'Abdullah', 'age': 22},
{'name': 'Citrus', 'age': 33},
{'name': 'Ben', 'age': 44},
{'name': 'Dough', 'age': 55}]
按年龄排序,因此列表按年龄升序返回。
尝试此代码以获得更好的理解。
解决方案 7:
lambda
and的另一种用法sorted
如下:
给定输入数组:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
该行:people_sort = sorted(people, key = lambda x: (-x[0], x[1]))
将给出people_sort
如下列表[[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]
在这种情况下,key=lambda x: (-x[0], x[1])
基本上告诉sorted
首先根据每个实例的第一个元素的值对数组进行排序(按减号所示的降序排列),然后在同一子组内,根据每个实例的第二个元素对数组进行排序(按升序排列,因为它是默认选项)。
希望这些信息对你有用!
解决方案 8:
lambda
是一个匿名函数,而不是任意函数。接受的参数将是您正在使用的变量以及您要对其进行排序的列。
解决方案 9:
由于在上下文中询问了 lambda 的使用sorted()
,所以也看一下这个https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions
解决方案 10:
换句话说,排序函数中的键(可选。要执行以决定顺序的函数。默认值为无)需要一个函数,并且您使用 lambda。
要定义 lambda,您需要指定要排序的对象属性,然后 python 的内置 sorted 函数将自动处理它。
如果您想按多个属性排序,那么分配键 = lambda x: (property1, property2)。
要指定 order-by,请传递 reverse = true 作为 sorted 函数的第三个参数(可选。布尔值。False 将按升序排序,True 将按降序排序。默认值为 False)。
扫码咨询,免费领取项目管理大礼包!