16

Is there any other argument than key, for example: value?

smci
  • 32,567
  • 20
  • 113
  • 146
zjm1126
  • 63,397
  • 81
  • 173
  • 221

3 Answers3

41

Arguments of sort and sorted

Both sort and sorted have three keyword arguments: cmp, key and reverse.

L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1

sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list

Using key and reverse is preferred, because they work much faster than an equivalent cmp.

key should be a function which takes an item and returns a value to compare and sort by. reverse allows to reverse sort order.

Using key argument

You can use operator.itemgetter as a key argument to sort by second, third etc. item in a tuple.

Example

>>> from operator import itemgetter

>>> a = range(5)
>>> b = a[::-1]
>>> c = map(lambda x: chr(((x+3)%5)+97), a)
>>> sequence = zip(a,b,c)

# sort by first item in a tuple
>>> sorted(sequence, key = itemgetter(0))
[(0, 4, 'd'), (1, 3, 'e'), (2, 2, 'a'), (3, 1, 'b'), (4, 0, 'c')]

# sort by second item in a tuple
>>> sorted(sequence, key = itemgetter(1))
[(4, 0, 'c'), (3, 1, 'b'), (2, 2, 'a'), (1, 3, 'e'), (0, 4, 'd')]

# sort by third item in a tuple
>>> sorted(sequence, key = itemgetter(2))
[(2, 2, 'a'), (3, 1, 'b'), (4, 0, 'c'), (0, 4, 'd'), (1, 3, 'e')]

Explanation

Sequences can contain any objects, not even comparable, but if we can define a function which produces something we can compare for each of the items, we can pass this function in key argument to sort or sorted.

itemgetter, in particular, creates such a function that fetches the given item from its operand. An example from its documentation:

After, f=itemgetter(2), the call f(r) returns r[2].

Mini-benchmark, key vs cmp

Just out of curiosity, key and cmp performance compared, smaller is better:

>>> from timeit import Timer
>>> Timer(stmt="sorted(xs,key=itemgetter(1))",setup="from operator import itemgetter;xs=range(100);xs=zip(xs,xs);").timeit(300000)
6.7079150676727295
>>> Timer(stmt="sorted(xs,key=lambda x:x[1])",setup="xs=range(100);xs=zip(xs,xs);").timeit(300000)
11.609490871429443
>>> Timer(stmt="sorted(xs,cmp=lambda a,b: cmp(a[1],b[1]))",setup="xs=range(100);xs=zip(xs,xs);").timeit(300000)
22.335839986801147

So, sorting with key seems to be at least twice as fast as sorting with cmp. Using itemgetter instead of lambda x: x[1] makes sort even faster.

sastanin
  • 40,473
  • 13
  • 103
  • 130
  • How can this work: `modNames.sort(key=lambda a: (a in data) and data.index(a))` (modNames, data are lists) ? – Mr_and_Mrs_D Oct 29 '14 at 20:37
  • Well, items in `modNames` that are in `data` will be sorted as they are in `data` - items that are not will be assigned key 0 and sorted in the beginning of the list along with the first item in data that also has key 0. – Mr_and_Mrs_D Jul 30 '19 at 10:35
  • Of note that `cmp` is deprecated in python3 – Mr_and_Mrs_D Jul 30 '19 at 10:37
3

Besides key=, the sort method of lists in Python 2.x could alternatively take a cmp= argument (not a good idea, it's been removed in Python 3); with either or none of these two, you can always pass reverse=True to have the sort go downwards (instead of upwards as is the default, and which you can also request explicitly with reverse=False if you're really keen to do that for some reason). I have no idea what that value argument you're mentioning is supposed to do.

smci
  • 32,567
  • 20
  • 113
  • 146
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • He just said "value" as an (out of place here) example because he's seen "key" and "value" mentioned together. – tzot Jan 08 '10 at 04:32
1

Yes, it takes other arguments, but no value.

>>> print list.sort.__doc__
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1

What would a value argument even mean?

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 3
    `help()` is generally more useful than printing `__doc__` directly. –  Dec 29 '09 at 04:22
  • 1
    I usually use ipython, and there one can write just `list.sort?` instead of `help(list.sort)` to get help. – sastanin Dec 29 '09 at 09:37