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?

1

6 Answers

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

operator is a built-in module providing a set of convenient operators. In two words operator.itemgetter(n) constructs a callable that assumes an iterable object (e.g. list, tuple, set) as input, and fetches the n-th element out of it.

So, you can't use key=a[x][1] there, because python has no idea what x is. Instead, you could use a lambda function (elem is just a variable name, no magic there):

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

Or just an ordinary function:

def get_second_elem(iterable): return iterable[1] a.sort(key=get_second_elem) 

So, here's an important note: in python functions are first-class citizens, so you can pass them to other functions as a parameter.

Other questions:

  1. Yes, you can reverse sort, just add reverse=True: a.sort(key=..., reverse=True)
  2. To sort by more than one column you can use itemgetter with multiple indices: operator.itemgetter(1,2), or with lambda: lambda elem: (elem[1], elem[2]). This way, iterables are constructed on the fly for each item in list, which are than compared against each other in lexicographic(?) order (first elements compared, if equal - second elements compared, etc)
  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.

Refer to the documentation for details:

  1. operator.itemgetter explained
  2. Sorting list by custom key in Python
6

Answer for Python beginners

In simpler words:

  1. The key= parameter of sort requires a key function (to be applied to be objects to be sorted) rather than a single key value and
  2. that is just what operator.itemgetter(1) will give you: A function that grabs the first item from a list-like object.

(More precisely those are callables, not functions, but that is a difference that can often be ignored.)

2

You are asking a lot of questions that you could answer yourself by reading the documentation, 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]) 

And reverse it:

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

Sort by more than one column:

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

See the sorting How To.

#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 
1
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. here is a sample code:

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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like