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
?
-
How does exactly Python sort the table? Can I reverse-sort it?
-
How can I sort it based on two columns like first age, and then if age is the same b name?
-
How could I do it without
operator
?
Solution 1:
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:
- Yes, you can reverse sort, just add
reverse=True
:a.sort(key=..., reverse=True)
- 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) - 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:
operator.itemgetter
explained- Sorting list by custom key in Python
Solution 2:
Answer for Python beginners
In simpler words:
- The
key=
parameter ofsort
requires a key function (to be applied to be objects to be sorted) rather than a single key value and - 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.)
Solution 3:
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.