排序后的语法(key=lambda:…)

我不太理解sorted()参数背后的语法:

key=lambda variable: variable[0]

lambda不是任意的吗?为什么variabledict中声明了两次?

321353 次浏览

lambda是一个用于生成匿名函数的Python关键字。

>>> (lambda x: x+2)(3)
5

:左边的variable是一个参数名。右边的variable使用了参数。

意思几乎完全相同:

def some_method(variable):
return variable[0]

lambda是一个匿名函数,不是任意函数。接受的参数将是您正在处理的变量,以及对其排序的列。

key是一个函数,将被调用来在比较集合的项之前转换它们。传递给key的参数必须是可调用的。

lambda的使用创建了一个匿名函数(它是可调用的)。在sorted的情况下,可调用对象只接受一个参数。Python的lambda非常简单。它实际上只能做和返回一件事。

lambda的语法是lambda这个词,后面跟着参数名列表,然后是一个单独的代码块。参数列表和代码块由冒号描述。这也类似于python中的其他结构,如whileforif等。它们都是通常具有代码块的语句。Lambda只是带有代码块的语句的另一个实例。

我们可以比较使用lambda和使用def来创建函数。

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

只是给了我们一种不指定名称的方法。这使得它很适合用作函数的参数。

variable在这里被使用了两次,因为在冒号的左边,它是一个参数的名称,在右边,它被用于在代码块中计算一些东西。

因为lambda的用法是在sorted()的上下文中被问到的,所以也来看看这个https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

我认为这里所有的答案都很好地涵盖了lambda函数在sorted()上下文中所做的核心,但是我仍然觉得缺乏一种导致直观理解的描述,所以这里是我的意见。

为了完整起见,我将在前面说明:sorted()返回一个已排序元素的列表,如果我们想以特定的方式排序,或者如果我们想对一个复杂的元素列表(例如嵌套列表或元组列表)排序,我们可以调用key参数。

对我来说,对关键参数的直观理解,为什么它必须是可调用的,以及使用lambda作为(匿名)可调用函数来完成这一点分为两部分。

  1. 使用lamba最终意味着您不必编写(定义)整个函数。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'
  1. 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函数使用x % 2 == 0中的mod操作符来优先考虑偶数。

第二,为什么偶数仍然是乱序的?2在6之前,对吧?

通过分析这个结果,我们将更深入地了解“key”参数是如何工作的,特别是与匿名lambda函数结合使用时。

首先,你会注意到,虽然概率出现在偶数之前,但偶数本身并没有排序。为什么会这样?让我们读一下文档:

从Python 2.4开始,list.sort()和sorted()都添加了一个键形参来指定要调用的函数

我们必须做一点字里行间的解读,但这告诉我们sort函数只被调用一次,如果我们指定key参数,那么我们根据key函数指向的值进行排序。

那么使用模的例子会返回什么呢?布尔值:True == 1False == 0。那么排序是如何处理这个键的呢?它基本上将原始列表转换为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函数计算出的布尔恒等式决定的,但请记住,这些子列表(one’s和zero)本身并不是按原始值排序的。因此,最终列表虽然按奇数和偶数排序,但没有按子列表排序(在这种情况下,偶数是无序的)。概率是有序的这一事实是因为它们在最初的列表中已经是有序的。所有这些的结论是,当lambda进行转换时,子列表的原始顺序被保留。

那么这一切是如何与最初的问题联系起来的,更重要的是,我们的直觉,我们应该如何实现sorted()与它的关键参数和lambda?

lambda函数可以被认为是指向我们需要排序的值的指针,无论是将值映射到由lambda函数转换的布尔值的指针,还是嵌套列表、元组、dict等中的特定元素,都是由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电话显然是说,“请对这个列表进行排序”。key参数使其更具体一些,它说:'对于mylist中的每个元素x,返回该元素的第二个索引,然后按照lambda函数计算的列表的排序顺序对原始列表mylist中的所有元素排序。由于我们有一个元组列表,我们可以使用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

运行该代码,您将发现这是顺序。尝试使用这个key函数对整数列表排序,您会发现代码崩溃了(为什么?因为你不能索引一个整数)。

这是一个冗长的解释,但我希望这有助于sort你对使用lambda函数的直觉-作为sorted()的关键参数,以及其他。

另一个使用key=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)]

换句话说,键(可选的。一个用来决定顺序的函数。默认为None)在排序函数中期望一个函数,您使用lambda。

定义lambda时,指定要排序的对象属性,python内置的sorted函数将自动处理。

如果你想按多个属性排序,那么分配key = lambda x:(property1, property2)。

要指定order-by,将reverse= true作为第三个参数(可选。一个布尔值。False将升序排序,True将降序排序。默认为False)的排序函数。

简单且不耗时的回答,并给出与所问问题相关的例子 如下示例:

 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}]

按年龄排序,因此列表按年龄升序返回。

为了更好地理解,请尝试以下代码。

lambdasorted的另一种用法如下:

给定输入数组: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 首先根据每个实例的第一个元素的值对数组排序(按照减号所示的下行顺序),而然后在同一子组中则根据每个实例的第二个元素排序(按照升序排序,因为这是默认选项)。

希望这是对你有用的信息!