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

时间:2012-01-23 02:09:18

标签: python sorting lambda custom-function

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

key=lambda variable: variable[0]

lambda不是随意的吗?为什么variable在看似dict的内容中说了两次?

10 个答案:

答案 0 :(得分:139)

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

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

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

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

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

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

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

答案 1 :(得分:102)

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

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

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

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

      

    lambda input_variable(s)美味一线

    e.g。

    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=时,它的真正含义是:当我一次遍历列表一个元素时(即列表中的e),我将把当前元素传递给我提供的函数在key参数中并使用它创建一个转换列表,它将通知我最终排序列表的顺序。
    2. 检查出来:

      mylist = [3,6,3,2,4,8,23]
      sorted(mylist, key=WhatToSortBy)
      

      基础示例:

      sorted(mylist)
      
        

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

      示例1:

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

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

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

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

      首先,你会注意到虽然赔率在平均值之前出现,但平均值并没有排序。为什么是这样?? Lets read the docs

        

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

      我们必须在这里的行之间进行一些阅读,但这告诉我们的是sort函数只被调用一次,如果我们指定了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函数确定的布尔标识(掩码)捆绑在一起。顺序由它们从lambda函数计算的布尔标识确定,但请记住,这些子列表(一个零和一个零)本身不是按其原始值排序的。因此,最终列表虽然由Odds和Evens组织,但没有按子列表排序(在这种情况下,均衡器无序)。订购赔率的事实是因为它们在原始列表中已经按顺序排列。所有这些的结论是,当lambda进行转换时,子列表的原始顺序将被保留。

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

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

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

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

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

        

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

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

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

答案 2 :(得分:25)

lambda是一个Python关键字,用于generate anonymous functions

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

答案 3 :(得分:12)

variable左侧的:是参数名称。在右边使用variable就是使用参数。

意味着几乎完全相同:

def some_method(variable):
  return variable[0]

答案 4 :(得分:4)

使用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)]

答案 5 :(得分:3)

lambda是一个匿名函数,而不是一个任意函数。接受的参数将是您正在使用的变量,以及您要对其进行排序的列。

答案 6 :(得分:3)

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

 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 :(得分:2)

由于在sorted()的上下文中询问了lambda的使用情况,因此请同时查看https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

答案 8 :(得分:1)

仅需改写一下,已排序函数中的键(可选。要执行以决定顺序的函数。默认为无)需要一个函数,而您使用的是lambda。

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

如果要按多个属性排序,则分配key = lambda x :(属性1,属性2)。

要指定排序方式,请将sorted函数的第三个参数(可选。布尔值。False升序排列,True降序排列。默认值为False)传递reverse = true。

答案 9 :(得分:1)

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 首先根据每个实例的第一个元素的值对数组进行排序(在降序 减号表示的顺序),然​​后然后在同一子组内,根据每个实例的第二个元素进行排序(按升序排列,因为它是默认选项)。< /p>

希望这对你有用!