operator.itemgetter() 和 sort() 是如何工作的?
Posted
技术标签:
【中文标题】operator.itemgetter() 和 sort() 是如何工作的?【英文标题】:How do operator.itemgetter() and sort() work? 【发布时间】:2013-09-06 21:20:06 【问题描述】:我有以下代码:
# initialize
a = []
# create the table (name, age, job)
a.append(["Nick", 30, "Doctor"])
a.append(["John", 8, "Student"])
a.append(["Paul", 22, "Car Dealer"])
a.append(["Mark", 66, "Retired"])
# sort the table by age
import operator
a.sort(key=operator.itemgetter(1))
# print the table
print(a)
它创建一个 4x3 表,然后按年龄对其进行排序。我的问题是,key=operator.itemgetter(1)
到底是做什么的? operator.itemgetter
函数是否返回项目的值?为什么我不能在那里输入key=a[x][1]
之类的东西?或者我可以吗?运算符如何打印表单的某个值,例如3x2
,即22
?
Python 究竟是如何对表格进行排序的?我可以对其进行反向排序吗?
如何根据第一年龄等两列对它进行排序,然后如果年龄是相同的 b 名称?
没有operator
怎么办?
【问题讨论】:
与本帖相关***.com/questions/3121979/… 【参考方案1】:看起来你对所有这些东西有点困惑。
operator
是一个内置模块,提供了一组方便的操作符。简而言之,operator.itemgetter(n)
构造了一个可调用对象,该可调用对象假定一个可迭代对象(例如列表、元组、集合)作为输入,并从中获取第 n 个元素。
所以,你不能在那里使用key=a[x][1]
,因为python 不知道x
是什么。相反,您可以使用 lambda
函数(elem
只是一个变量名,没有任何魔法):
a.sort(key=lambda elem: elem[1])
或者只是一个普通的函数:
def get_second_elem(iterable):
return iterable[1]
a.sort(key=get_second_elem)
所以,这里有一个重要的说明:在python中函数是first-class citizens,所以你可以将它们作为参数传递给其他函数。
其他问题:
-
是的,你可以反向排序,只需添加
reverse=True
:a.sort(key=..., reverse=True)
要按多列排序,您可以使用 itemgetter
和多个索引:operator.itemgetter(1,2)
,或使用 lambda:lambda elem: (elem[1], elem[2])
。这样,可以为列表中的每个项目动态构建可迭代对象,然后按字典顺序(?)相互比较(比较第一个元素,如果相等 - 比较第二个元素等)
您可以使用a[2,1]
获取[3,2] 处的值(索引从零开始)。使用运算符...这是可能的,但不如索引那么干净。
详情请参阅文档:
operator.itemgetter
explained
Sorting list by custom key in Python
【讨论】:
你将如何排序由一列反转而不是由另一列反转?operator.itemgetter(n)
似乎不适用于set
或dict
(如果n
是有效密钥而不是一些int
你来了,它可能与dict
一起使用与)。
@Vim According to docs,对于 dict 它应该适用于任何可散列值。 itemgetter(n)
表示它将尝试执行 dict.__getitem__ 查找,这(除非您实际上没有使用 dict,而是扩展 dict 并覆盖 getitem 的自定义类)相当于 dict[n]
- 如果字典中没有n
键,它显然会失败。对于您不确定是否存在密钥的字典,您可能想要坚持使用 lambda key: dict.get(key, None)
或类似的东西。示例:ideone.com/PJk8vd
@yayitswei 如果一列是数字,则使用lambda row: (row.one_thing, -row.number_thing)
,如果您想通过one_thing
反转,则提供reverse=True
。如果您没有像这样简单的数字选项,您将不得不进行更多操作。
@yahyitswei 是的,请在此处查看 itemgetter 排序解决方案以了解多列的不同反向参数,然后您需要连续多个步骤安排排序:***.com/questions/14466068/…【参考方案2】:
给 Python 初学者的答案
简单来说:
sort
的key=
参数需要一个键函数(应用于要排序的对象)而不是单个键值 和李>
这正是operator.itemgetter(1)
将为您提供的:一个函数,它从一个类似列表的对象中获取第一个项目。
(更准确地说,那些是 callables,而不是函数,但这是一个经常可以忽略的区别。)
【讨论】:
谢谢 - 作为一个仍在学习的 Python 程序员,这就是我想要了解正在发生的事情。我不清楚我的代码中的 ".sort(key = attrgetter("index"))" 是否将带有参数 "index" 的 FUNCTION attrgetter() 发送到 Sort() 函数;我以为它是用 C 和其他语言发送结果。 @Locane:不,这不是正在发生的事情。attrgetter
将为您构造一个适当的函数并返回它。它正在发送“结果”。只有那个结果才是一个函数。【参考方案3】:
你问了很多问题,你可以通过reading the documentation 自己回答,所以我会给你一个一般性的建议:阅读它并在 python shell 中进行实验。你会看到itemgetter
返回一个可调用对象:
>>> func = operator.itemgetter(1)
>>> func(a)
['Paul', 22, 'Car Dealer']
>>> func(a[0])
8
要以不同的方式执行此操作,您可以使用lambda
:
a.sort(key=lambda x: x[1])
然后反转它:
a.sort(key=operator.itemgetter(1), reverse=True)
按多列排序:
a.sort(key=operator.itemgetter(1,2))
请参阅sorting How To。
【讨论】:
【参考方案4】:#sorting first by age then profession,you can change it in function "fun".
a = []
def fun(v):
return (v[1],v[2])
# create the table (name, age, job)
a.append(["Nick", 30, "Doctor"])
a.append(["John", 8, "Student"])
a.append(["Paul", 8,"Car Dealer"])
a.append(["Mark", 66, "Retired"])
a.sort(key=fun)
print a
【讨论】:
此方案不使用操作符【参考方案5】:a = []
a.append(["Nick", 30, "Doctor"])
a.append(["John", 8, "Student"])
a.append(["Paul", 8,"Car Dealer"])
a.append(["Mark", 66, "Retired"])
print a
[['Nick', 30, 'Doctor'], ['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Mark', 66, 'Retired']]
def _cmp(a,b):
if a[1]<b[1]:
return -1
elif a[1]>b[1]:
return 1
else:
return 0
sorted(a,cmp=_cmp)
[['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Nick', 30, 'Doctor'], ['Mark', 66, 'Retired']]
def _key(list_ele):
return list_ele[1]
sorted(a,key=_key)
[['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Nick', 30, 'Doctor'], ['Mark', 66, 'Retired']]
>>>
【讨论】:
【参考方案6】:使用用户定义函数对数组进行排序的最简单方法是使用 Functools 中的 cmp_to_key。 这是一个示例代码:
from functools import cmp_to_key
def mine(x,y):
if(x[1]!=y[1]): return x[1]>y[1]
else: return x[0]>y[0]
a = []
a.append(["Nick", 30, "Doctor"])
a.append(["John", 8, "Student"])
a.append(["Paul", 22, "Car Dealer"])
a.append(["Mark", 66, "Retired"])
def mine(a,b):
if a[1] > b[1]:
return 1
elif a[1] < b[1]:
return -1
else:
if a[0] > b[0]:
return 1
else:
return 0
print(sorted(a,key = cmp_to_key(mine)))
【讨论】:
以上是关于operator.itemgetter() 和 sort() 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章