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=Truea.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) 似乎不适用于setdict (如果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 初学者的答案

简单来说:

    sortkey= 参数需要一个键函数(应用于要排序的对象)而不是单个键 和李> 这正是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() 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

operator.itemgetter函数

python中operator.itemgetter函数

python operator itemgetter()

关于python中的operator.itemgetter()函数的用法

python中的operator.itemgetter函数

Python中的sorted函数以及operator.itemgetter函数