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

key=lambda variable: variable[0]

不是任意的吗?为什么变量声明两次在什么看起来像字典?


当前回答

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

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

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

使用lamba最终意味着您不必编写(定义)整个函数。Lambda函数被创建、使用并立即销毁——因此它们不会因为更多只会使用一次的代码而破坏您的代码。根据我的理解,这是lambda函数的核心功能,它在这种角色上的应用是广泛的。它的语法纯粹是一种约定,这在本质上是一般编程语法的本质。学习语法并完成它。

Lambda语法如下:

lambda input_variable(s): tasty one liner

其中lambda是python关键字。

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'

key参数背后的思想是,它应该接受一组指令,这些指令本质上是将'sorted()'函数指向那些应该用于排序的列表元素。当它说key=时,它真正的意思是:当我遍历列表时,一次一个元素(即some_list中的e),我将把当前元素传递给由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函数在排序前检查每个元素e是偶数还是奇数。

但是等等!你可能(或者应该)想知道两件事。

首先,为什么奇数出现在偶数之前?毕竟,键值似乎是在告诉排序函数使用x % 2 == 0中的mod操作符来优先考虑偶数。

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

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

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

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

我们必须做一点字里行间的解读,但这告诉我们sort函数只被调用一次,如果我们指定key参数,那么我们根据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]

Okay, so now we know why the odds come before the evens. But the next question is: Why does the 6 still come before the 2 in my final list? Well that's easy - it is because sorting only happens once! Those 1s still represent the original list values, which are in their original positions relative to each other. Since sorting only happens once, and we don't call any kind of sort function to order the original even numbers from low to high, those values remain in their original order relative to one another.

最后一个问题是:当我打印出最终排序的列表时,我如何从概念上考虑布尔值的顺序如何转换回原始值?

Sorted() is a built-in method that (fun fact) uses a hybrid sorting algorithm called Timsort that combines aspects of merge sort and insertion sort. It seems clear to me that when you call it, there is a mechanic that holds these values in memory and bundles them with their boolean identity (mask) determined by (...!) the lambda function. The order is determined by their boolean identity calculated from the lambda function, but keep in mind that these sublists (of one's and zeros) are not themselves sorted by their original values. Hence, the final list, while organized by Odds and Evens, is not sorted by sublist (the evens in this case are out of order). The fact that the odds are ordered is because they were already in order by coincidence in the original list. The takeaway from all this is that when lambda does that transformation, the original order of the sublists are retained.

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

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

我的排序电话显然是说,“请对这个列表进行排序”。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函数对整数列表排序,您会发现代码崩溃了(为什么?因为你不能索引一个整数)。

其他回答

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

>>> (lambda x: x+2)(3)
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"]))

看看名单上的名字,他们以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}]

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

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

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

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

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

使用lamba最终意味着您不必编写(定义)整个函数。Lambda函数被创建、使用并立即销毁——因此它们不会因为更多只会使用一次的代码而破坏您的代码。根据我的理解,这是lambda函数的核心功能,它在这种角色上的应用是广泛的。它的语法纯粹是一种约定,这在本质上是一般编程语法的本质。学习语法并完成它。

Lambda语法如下:

lambda input_variable(s): tasty one liner

其中lambda是python关键字。

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'

key参数背后的思想是,它应该接受一组指令,这些指令本质上是将'sorted()'函数指向那些应该用于排序的列表元素。当它说key=时,它真正的意思是:当我遍历列表时,一次一个元素(即some_list中的e),我将把当前元素传递给由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函数在排序前检查每个元素e是偶数还是奇数。

但是等等!你可能(或者应该)想知道两件事。

首先,为什么奇数出现在偶数之前?毕竟,键值似乎是在告诉排序函数使用x % 2 == 0中的mod操作符来优先考虑偶数。

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

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

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

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

我们必须做一点字里行间的解读,但这告诉我们sort函数只被调用一次,如果我们指定key参数,那么我们根据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]

Okay, so now we know why the odds come before the evens. But the next question is: Why does the 6 still come before the 2 in my final list? Well that's easy - it is because sorting only happens once! Those 1s still represent the original list values, which are in their original positions relative to each other. Since sorting only happens once, and we don't call any kind of sort function to order the original even numbers from low to high, those values remain in their original order relative to one another.

最后一个问题是:当我打印出最终排序的列表时,我如何从概念上考虑布尔值的顺序如何转换回原始值?

Sorted() is a built-in method that (fun fact) uses a hybrid sorting algorithm called Timsort that combines aspects of merge sort and insertion sort. It seems clear to me that when you call it, there is a mechanic that holds these values in memory and bundles them with their boolean identity (mask) determined by (...!) the lambda function. The order is determined by their boolean identity calculated from the lambda function, but keep in mind that these sublists (of one's and zeros) are not themselves sorted by their original values. Hence, the final list, while organized by Odds and Evens, is not sorted by sublist (the evens in this case are out of order). The fact that the odds are ordered is because they were already in order by coincidence in the original list. The takeaway from all this is that when lambda does that transformation, the original order of the sublists are retained.

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

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

我的排序电话显然是说,“请对这个列表进行排序”。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函数对整数列表排序,您会发现代码崩溃了(为什么?因为你不能索引一个整数)。

左边的变量是一个参数名。右边变量的使用是利用了参数。

意思几乎完全相同:

def some_method(variable):
  return variable[0]

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

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

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

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