How do operator.itemgetter() and sort() work?

I have the following code:

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

It creates a 4x3 table and then it sorts it by age. My question is, what exactly key=operator.itemgetter(1) does? Does the operator.itemgetter function return the item's value? Why can't I just type something like key=a[x][1] there? Or can I? How could with operator print a certain value of the form like 3x2 which is 22?

  1. How does exactly Python sort the table? Can I reverse-sort it?

  2. How can I sort it based on two columns like first age, and then if age is the same b name?

  3. How could I do it without operator?

252664 次浏览

You are asking a lot of questions that you could answer yourself by 阅读文件, so I'll give you a general advice: read it and experiment in the python shell. You'll see that itemgetter returns a callable:

>>> func = operator.itemgetter(1)
>>> func(a)
['Paul', 22, 'Car Dealer']
>>> func(a[0])
8

To do it in a different way, you can use lambda:

a.sort(key=lambda x: x[1])

然后反过来:

a.sort(key=operator.itemgetter(1), reverse=True)

按多个列排序:

a.sort(key=operator.itemgetter(1,2))

看看 如何分类

Looks like you're a little bit confused about all that stuff.

operator是一个内置的模块,提供了一套方便的操作符。简而言之,operator.itemgetter(n)构造了一个可调用的对象,它假定一个可迭代的对象(例如 list、 tuple、 set)作为输入,并从中获取第 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. Yes, you can reverse sort, just add reverse=True: a.sort(key=..., reverse=True)
  2. 要按多个列进行排序,可以使用带有多个索引的 itemgetter: operator.itemgetter(1,2),或者使用带有 lambda: lambda elem: (elem[1], elem[2])itemgetter。通过这种方式,对列表中的每个项目动态构造迭代,然后在词典学(?)中相互比较顺序(第一个元素比较,如果等于第二个元素比较等)
  3. You can fetch value at [3,2] using a[2,1] (indices are zero-based). Using operator... It's possible, but not as clean as just indexing.

详情请参阅文件:

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

Python 初学者的答案

简而言之:

  1. sortkey=参数需要一个键 功能(应用于要排序的对象) ,而不是一个键 价值
  2. 这正是 operator.itemgetter(1)将给你的: 一个从类似列表的对象中抓取第一个项目的 function

(更确切地说,它们是 可打电话,而不是函数,但这种差异通常可以忽略。)

#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
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']]
>>>

The easiest way to sort an array using a user-defined function is to use cmp_to_key from Functools. 下面是一个示例代码:

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