sorted(key=lambda: ...) 背后的语法[重复]

2025-01-16 08:38:00
admin
原创
122
摘要:问题描述:我不太明白这个sorted()论点背后的语法:key=lambda variable: variable[0] 这不是lambda任意的吗?为什么variable在看起来像 的地方两次提到dict?解决方案 1:我认为这里的所有答案都很好地涵盖了 lambda 函数在上下文中所做的核心内容sorte...

问题描述:

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

key=lambda variable: variable[0]

这不是lambda任意的吗?为什么variable在看起来像 的地方两次提到dict


解决方案 1:

我认为这里的所有答案都很好地涵盖了 lambda 函数在上下文中所做的核心内容sorted(),但我仍然觉得缺乏能够让人直观理解的描述,所以这里是我的看法。

为了完整起见,我将首先说明显而易见的事情:sorted()返回已排序元素的列表,如果我们想以特定方式排序,或者如果我们想对复杂的元素列表(例如嵌套列表或元组列表)进行排序,我们可以调用关键参数。

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

  1. 使用 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'
  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函数优先考虑偶数。mod`x % 2 == 0`

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

通过分析这个结果,我们将更深入地了解“key”参数的实际工作原理,尤其是与匿名 lambda 函数结合使用时。

首先,你会注意到,虽然奇数排在偶数之前,但偶数本身并没有排序。这是为什么呢?让我们阅读文档:

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

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

那么使用模数的示例会返回什么呢?一个布尔值:True == 1False == 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:

lambdaand的另一种用法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)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3892  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2717  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   52  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   54  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   49  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用