Syntax behind sorted(key=lambda: …)
我不太了解
1 | key=lambda variable: variable[0] |
我们可以将lambda与def的使用进行比较,以创建一个函数。
1 2 | adder_lambda = lambda parameter1,parameter2: parameter1+parameter2 def adder_regular(parameter1, parameter2): return parameter1+parameter2 |
lambda只是为我们提供了一种无需分配名称的方法。这非常适合用作函数的参数。
我认为这里的所有答案都很好地涵盖了lambda函数在sorted()上下文中的作用的核心,但是我仍然感觉缺乏对直观理解的描述,因此这里只有我的两分钱。
为了完整起见,我先说一下显而易见的事情:sorted()返回已排序元素的列表,以及是否要以特定方式排序或是否要对元素的复杂列表进行排序(例如,嵌套列表或元组列表),我们可以调用key参数。
对我来说,关键参数的直观理解,为什么它必须是可调用的以及使用lambda作为(匿名)可调用函数来完成此操作的过程分为两个部分。
Lambda语法如下:
lambda input_variable(s): tasty one liner
Ok.
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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' |
看看这个:
1 2 | mylist = [3,6,3,2,4,8,23] sorted(mylist, key=WhatToSortBy) |
基本示例:
1 | sorted(mylist) |
[2, 3, 3, 4, 6, 8, 23] # all numbers are in order from small to large.
Ok.
范例1:
1 2 | mylist = [3,6,3,2,4,8,23] sorted(mylist, key=lambda x: x%2==0) |
[3, 3, 23, 6, 2, 4, 8] # Does this sorted result make intuitive sense to you?
Ok.
请注意,我的lambda函数告诉sorted在排序之前检查(e)是偶数还是奇数。
可是等等!您可能(也许应该)想知道两件事-首先,为什么我的赔率比我的赔率还要高(因为我的关键值似乎是在告诉我排序的函数通过使用
首先,您会注意到虽然赔率先于偶数,但偶数本身并未排序。为什么是这样??让我们阅读文档:
Key Functions Starting with Python 2.4, both list.sort() and sorted() added a key parameter to specify a function to be called on
each list element prior to making comparisons.Ok.
我们必须在这里在行与行之间进行一些读取,但这告诉我们,sort函数仅被调用一次,并且如果我们指定key参数,那么我们将按key函数指向我们的值进行排序。
那么使用模数返回的示例又是什么呢?布尔值:
[3,6,3,2,4,8,23] becomes [0,1,0,1,1,1,0]
Ok.
现在我们到了某个地方。对转换后的列表进行排序会得到什么?
[0,0,0,1,1,1,1]
Ok.
好的,现在我们知道了为什么赔率要高于平均赔率了。但是下一个问题是:为什么最终列表中的6仍然排在2之前?嗯,这很容易-因为排序只发生一次!即那些1仍代表原始列表值,它们处于彼此相对的原始位置。由于排序仅发生一次,并且我们不调用任何排序函数来将原始偶数值从低到高排序,因此这些值相对于彼此保持原始顺序。
那么最后的问题是:当我打印出最终的排序列表时,我如何在概念上思考布尔值的顺序如何转换回原始值?
Sorted()是一种内置方法,(事实)使用称为Timsort的混合排序算法,该算法结合了合并排序和插入排序的各个方面。在我看来,当您调用它时,有一种机制可以将这些值保存在内存中,并将它们与由(...!)lambda函数确定的布尔标识(掩码)捆绑在一起。顺序由通过lambda函数计算的布尔身份确定,但请记住,这些子列表(一个和一个零)本身并不按其原始值排序。因此,最终列表虽然由奇数和偶数组成,但不会按子列表排序(在这种情况下,偶数是乱序的)。赔率排序的事实是因为它们在原始列表中已经是巧合了。从所有这些中得出的结论是,当lambda进行该转换时,将保留子列表的原始顺序。
那么,这一切与原始问题有何关系,更重要的是,我们对如何使用关键参数和lambda实现sorted()的直觉?
该lambda函数可以被认为是指向我们需要排序的值的指针,它是将值映射到由lambda函数转换后的布尔值的指针,还是其嵌套列表元组中的特定元素, dict等,同样由lambda函数
让我们尝试预测运行以下代码时会发生什么。
1 2 | mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)] sorted(mylist, key=lambda x: x[1]) |
我的
[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]
Ok.
运行该代码,您会发现这是命令。尝试索引整数列表,您会发现代码中断。
这是一个冗长的解释,但是我希望这有助于对使用lambda函数作为sorted()及以后的关键参数的"直觉"进行"整理"。
好。
1 2 | >>> (lambda x: x+2)(3) 5 |
意思几乎完全相同:
1 2 | def some_method(variable): return variable[0] |
使用key = lambda的sorted()函数的另一个示例。让我们考虑一下您有一个元组列表。在每个元组中,您都有汽车的品牌,型号和重量,并且您想要按品牌,型号或重量对这个元组列表进行排序。您可以使用lambda做到这一点。
1 2 3 4 5 | 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])) |
结果:
1 2 3 | [('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000)] [('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100)] [('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700')] |
由于在
换个说法,排序函数中的键(可选。要执行以决定顺序的函数。默认为None)需要一个函数,而您使用的是lambda。
要定义lambda,请指定要排序的对象属性,python的内置排序函数将自动处理它。
如果要按多个属性排序,则分配key = lambda x:(property1,property2)。
要指定排序方式,请将sorted函数的第三个参数(可选。布尔值。False将按升序排序,True将按降序排序。默认值为False)传递reverse = true。