operator.itemgetter()和sort()如何工作?


75

我有以下代码:

# 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]?可以吗 用运算符如何打印像3x2is这样的表格的某个值22

  1. Python到底如何对表格进行排序?我可以对它进行反向排序吗?

  2. 我如何基于两列(例如第一个年龄,然后如果年龄是相同的b名称)对其进行排序?

  3. 没有我怎么办operator


Answers:


119

看起来您对所有这些东西有些困惑。

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函数是一等公民,因此您可以将它们作为参数传递给其他函数。

其他问题:

  1. 是的,您可以反向排序,只需添加reverse=Truea.sort(key=..., reverse=True)
  2. 要按多个列进行排序,您可以将itemgetter多个index:operator.itemgetter(1,2)或lambda:一起使用lambda elem: (elem[1], elem[2])。这样,可迭代地为列表中的每个项目构造可迭代变量,然后按lexicographic(?)顺序将它们相互比较(比较第一个元素,如果相等,则比较第二个元素等)
  3. 您可以使用a[2,1][索引为0的索引]在[3,2]处获取值。使用运算符...可能,但是不像索引那样干净。

有关详细信息,请参阅文档:

  1. operator.itemgetter 解释
  2. 在Python中按自定义键排序列表

1
您将如何对一列反转而不是另一列反转排序?
yayitswei

operator.itemgetter(n)似乎无法使用setdict(或者,dict如果n是有效的密钥而不是int您想出的一些密钥,那么它将可以使用)。
Vim

1
@Vim根据docs,它应该与任何可哈希值一起工作。itemgetter(n)意味着它会尝试做字典.__ getitem__查找,这(除非你不实际使用的字典,而是一个自定义类扩展字典和压倒一切的GetItem)相当于dict[n]-如果没有这显然会失败n的关键字典 对于不确定某个键是否存在的字典,您可能想要坚持使用lambda key: dict.get(key, None)类似的东西。示例:ideone.com/PJk8vd
J0HN

1
@yayitswei如果一列是数字,请使用lambda row: (row.one_thing, -row.number_thing)reverse=True如果要通过进行反向,请提供one_thing。如果您没有像这样简单的数字选项,则必须花更多的钱。
pydsigner

1
@yahyitswei是,请参阅这里不同的多个列反向参数的itemgetter排序的解决方案,那么你需要安排您的排序中连续多个步骤:stackoverflow.com/questions/14466068/...
questionto42

34

Python初学者的答案

简单来说:

  1. key=参数sort需要键功能(将其应用为要排序的对象),而不是单个键
  2. 这就是operator.itemgetter(1)给您的东西:一个功能,该从类似列表的对象中获取第一项。

(更确切地说,这些是可调用的,而不是函数,但这是一个经常可以忽略的区别。)


谢谢您-作为一名仍在学习中的python程序员,我一直在寻找这是为了了解正在发生的事情。我不清楚代码中的“ .sort(key = attrgetter(” index“))”是将带有参数“ index”的FUNCTION attrgetter()发送到Sort()函数;我以为它以C语言和其他语言发送结果。
Locane

4
@Locane:不,那不是事实。attrgetter将为您构造一个适当的函数并将其返回。它正在发送“结果”。只有那个结果才是函数。
Lutz Prechelt

15

您会问很多问题,可以通过阅读文档回答自己,所以我将给您一个一般性的建议:阅读并在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))

请参阅如何排序


0
#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

2
此解决方案无需使用运算符
user2329366 '16

0
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']]
>>> 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.