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

Chr*_*eta 137 python sorting lambda custom-function

我不太明白这个sorted()论点背后的语法:

key=lambda variable: variable[0]
Run Code Online (Sandbox Code Playgroud)

不是lambda随意的吗?为什么variable在看起来像是两次dict

Eva*_*van 146

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

使用lambda创建一个匿名函数(可调用).在sorted可调用的情况下只需要一个参数.Python lambda非常简单.它只能真正做到并归还一件事.

语法lambdalambda后跟参数名列表的单词,然后是单个代码块.参数列表和代码块由冒号表示.这是在python类似于其他构建体,以及诸如while,for,if等.它们都是通常具有代码块的语句.Lambda只是带有代码块的语句的另一个实例.

我们可以比较lambda和def的使用来创建一个函数.

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2
Run Code Online (Sandbox Code Playgroud)

lambda只是为我们提供了一种不用指定名称的方法.这使得它非常适合用作函数的参数.

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

  • note(对OP):应该避免将lambda指定给一个名称(即以非匿名函数的方式使用它).如果你发现自己这样做,你应该只使用`def`. (9认同)

Pau*_*ulG 122

我认为这里的所有答案都涵盖了lambda函数在sorted()的上下文中所做的很好的核心,但是我仍然感觉像是一个缺乏直观理解的描述,所以这是我的两分钱.

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

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

  1. 使用lamba最终意味着你不必编写(定义)整个函数,就像一个sblom提供的一个例子.Lambda函数被创建,使用并立即销毁 - 因此它们不会使用更多只能使用一次的代码来放大代码.据我所知,这是lambda函数的核心实用程序,它对这些角色的应用是广泛的.它的语法纯粹是通过约定,这实际上是程序语法的本质.学习语法并完成它.

Lambda语法如下:

lambda input_variable(s):美味的一个衬垫

例如

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'
Run Code Online (Sandbox Code Playgroud)
  1. 这个key论点背后的想法是它应该接受一组指令,这些指令基本上将'sorted()'函数指向应该用于排序的那些列表元素.当它说key=,它的真正含义是:当我一次遍历列表一个元素(即列表中的e)时,我将把当前元素传递给我在key参数中提供的函数并使用它创建一个转换列表,告诉我最终排序列表的顺序.

看看这个:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)
Run Code Online (Sandbox Code Playgroud)

基础示例:

sorted(mylist)
Run Code Online (Sandbox Code Playgroud)

[2,3,3,4,6,8,23]#所有数字按从小到大的顺序排列.

例1:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)
Run Code Online (Sandbox Code Playgroud)

[3,3,23,6,2,4,8]#这个排序结果对你有直觉意义吗?

请注意,我的lambda函数告诉已排序,以便在排序之前检查(e)是偶数还是奇数.

可是等等!你可能(或者应该)想知道两件事 - 首先,为什么我的赔率在我的平均值之前(因为我的键值似乎告诉我的排序函数通过使用mod运算符来优先考虑均衡x%2==0).第二,为什么我的平均故障?2来到6之前吧?通过分析这个结果,我们将更深入地了解sorted()'key'参数如何工作,特别是与匿名lambda函数结合使用.

首先,你会注意到虽然赔率在平均值之前,但是平均值并没有排序.为什么是这样??让我们阅读文档:

关键函数从Python 2.4开始,list.sort()和sorted()都添加了一个关键参数,用于指定在进行比较之前在每个列表元素上调用的函数.

我们必须在这里的行之间进行一些阅读,但是这告诉我们的是sort函数只调用一次,如果我们指定key参数,那么我们按键函数指向的值排序.

那么使用模数返回的示例是什么?布尔值:True == 1,False == 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函数确定的布尔标识(掩码)捆绑在一起.顺序由它们从lambda函数计算的布尔标识确定,但请记住,这些(一个和零的)子列表本身不是按原始值排序的.因此,最终列表虽然由Odds和Evens组织,但没有按子列表排序(在这种情况下,均衡器无序).订购赔率的事实是因为它们在原始列表中已经按顺序排列.所有这些的结论是,当lambda进行转换时,子列表的原始顺序将被保留.

那么这一切如何与原始问题有关,更重要的是,我们对如何使用其关键参数和lambda实现sorted()的直觉?

lambda函数可以被认为是指向我们需要排序的值的指针,无论是将值映射到由lambda函数转换的boolean值的指针,还是它是嵌套列表中的特定元素,元组, dict等,再次由lambda函数决定.

让我们尝试预测当我运行以下代码时会发生什么.

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])
Run Code Online (Sandbox Code Playgroud)

我的sorted电话显然说:"请排序此列表".关键参数通过说明,对于mylist中的每个元素(x),返回该元素的索引1,然后按照由列表计算的列表的排序顺序对原始列表"mylist"的所有元素进行排序,使得更具体一点. lambda函数.由于我们有一个元组列表,我们可以从该元组返回一个索引元素.所以我们得到:

[(6,2,8),(3,5,5),(6,8,5),(2,9,4)]

运行该代码,您会发现这是订单.尝试索引整数列表,你会发现代码中断了.

这是一个冗长的解释,但我希望这有助于"排序"你对使用lambda函数作为sorted()及更高版本中的关键参数的直觉.

  • 优秀而全面的解释.这个答案值得100分.但我想知道为什么喜欢这个答案的人少了. (6认同)
  • 谢谢你的深刻解释.我[阅读文档](https://docs.python.org/3/library/functions.html#sorted)并对操作方法进行排序,我不清楚`key`函数背后的想法.如果你试图理解`sorted`函数,那么`lambda`语法就会深入理解. (3认同)
  • 这是最好的解释.这对于帮助我理解它实际上是如何工作非常有用 - 我理解了lambda函数,但在sorted()的上下文中使用它没有任何意义.这真的很有帮助,谢谢! (3认同)
  • 这是一个绝妙的答案。先生,向您问好。 (2认同)
  • 这是我最喜欢的堆栈溢出答案之一。谢谢! (2认同)
  • @PaulG - 这是一个很好的解释,当时我无法将其记在心里。你应该写一本书。 (2认同)

Ign*_*ams 25

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

>>> (lambda x: x+2)(3)
5
Run Code Online (Sandbox Code Playgroud)

  • parens在'3'附近,因为它被传递给一个函数.parens在lambda周围,因此表达式不被解析为`lambda x:x + 2(3)`,这是无效的,因为`2`不是函数. (19认同)
  • 为什么每个都有括号? (2认同)

sbl*_*lom 12

variable左边:是一个参数的名字.采用variable右侧正在使用的参数.

意思几乎完全相同:

def some_method(variable):
  return variable[0]
Run Code Online (Sandbox Code Playgroud)


fil*_*r36 7

使用sorted()函数和 key=lambda 的另一个例子。假设您有一个元组列表。在每个元组中,您都有汽车的品牌、型号和重量,并且您希望按品牌、型号或重量对这个元组列表进行排序。你可以用 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]))
Run Code Online (Sandbox Code Playgroud)

结果:

[('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)]
Run Code Online (Sandbox Code Playgroud)


Abd*_*S96 5

简单且不耗时的答案,并提供与所问问题相关的示例 请遵循以下示例:

 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"]))
Run Code Online (Sandbox Code Playgroud)

看看列表中的名字,他们以 D、B、C 和 A 开头。如果你注意到年龄,他们是 55、44、33 和 22。第一个打印代码

print(sorted(user, key=lambda el: el["name"]))
Run Code Online (Sandbox Code Playgroud)

结果:

[{'name': 'Abdullah', 'age': 22}, 
{'name': 'Ben', 'age': 44}, 
{'name': 'Citrus', 'age': 33}, 
{'name': 'Dough', 'age': 55}]
Run Code Online (Sandbox Code Playgroud)

对名称进行排序,因为通过 key=lambda el: el["name"] 我们对名称进行排序,并且名称按字母顺序返回。

第二次打印代码

print(sorted(user, key= lambda y: y["age"]))
Run Code Online (Sandbox Code Playgroud)

结果:

[{'name': 'Abdullah', 'age': 22},
 {'name': 'Citrus', 'age': 33},
 {'name': 'Ben', 'age': 44}, 
 {'name': 'Dough', 'age': 55}]
Run Code Online (Sandbox Code Playgroud)

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

尝试这段代码以更好地理解。


归档时间:

查看次数:

169965 次

最近记录:

5 年,10 月 前