17

I want to sort this info(name, points, and time):

list = [
    {'name':'JOHN', 'points' : 30, 'time' : '0:02:2'},
    {'name':'KARL','points':50,'time': '0:03:00'}
]

so, what I want is the list sorted first by points made, then by time played (in my example, matt go first because of his less time. any help?

I'm trying with this:

import operator
list.sort(key=operator.itemgetter('points', 'time'))

but got a TypeError: list indices must be integers, not str.

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
dobleseis
  • 629
  • 2
  • 7
  • 12
  • What version of python? Your example works on 2.7. Also, as a reminder "list" is a typename. – koblas May 10 '11 at 02:57
  • 1
    @koblas I might be to blame. This example works for me too now, but I edited the question to format the source code, and inadvertently corrected a syntax error in the definition of ``list``. Ignoring the fact that the variable name ``list`` clobbers a builtin, once the syntax error of an incorrectly terminated string literal was fixed, things work... – Jarret Hardie May 10 '11 at 03:01
  • Can't be a python version issue, I use python 2.6.6. And sorry, my fault, in fact list is not my variable name, I don't know why I use it here. I think there is something wrong with the "time played" that I have converted to string... – dobleseis May 10 '11 at 11:02

3 Answers3

27

Your example works for me. I would advise you not to use list as a variable name, since it is a builtin type.

You could try doing something like this also:

list.sort(key=lambda item: (item['points'], item['time']))
Ponkadoodle
  • 5,777
  • 5
  • 38
  • 62
9

edit:

example list:

>>> a = [
...     {'name':'JOHN', 'points' : 30, 'time' : '0:02:20'},
...     {'name':'LEO', 'points' : 30, 'time': '0:04:20'},
...     {'name':'KARL','points':50,'time': '0:03:00'},
...     {'name':'MARK','points':50,'time': '0:02:00'},
... ]

descending 'points':

using sort() for inplace sorting:

>>> a.sort(key=lambda x: (-x['points'],x['time']))
>>> pprint.pprint(a)
[{'name': 'MARK', 'points': 50, 'time': '0:02:00'},
 {'name': 'KARL', 'points': 50, 'time': '0:03:00'},
 {'name': 'JOHN', 'points': 30, 'time': '0:02:20'},
 {'name': 'LEO', 'points': 30, 'time': '0:04:20'}]
>>> 

using sorted to return a sorted list:

>>> pprint.pprint(sorted(a, key=lambda x: (-x['points'],x['time'])))
[{'name': 'MARK', 'points': 50, 'time': '0:02:00'},
 {'name': 'KARL', 'points': 50, 'time': '0:03:00'},
 {'name': 'JOHN', 'points': 30, 'time': '0:02:20'},
 {'name': 'LEO', 'points': 30, 'time': '0:04:20'}]
>>> 

ascending 'points':

>>> a.sort(key=lambda x: (x['points'],x['time']))
>>> import pprint
>>> pprint.pprint(a)
[{'name': 'JOHN', 'points': 30, 'time': '0:02:20'},
 {'name': 'LEO', 'points': 30, 'time': '0:04:20'},
 {'name': 'MARK', 'points': 50, 'time': '0:02:00'},
 {'name': 'KARL', 'points': 50, 'time': '0:03:00'}]
>>> 
dting
  • 38,604
  • 10
  • 95
  • 114
  • In your example, MARK should be the first, because he has more points, KARL 2nd (same points but more time), and so on.. – dobleseis May 10 '11 at 11:05
  • fixed, you wanted to sort the reverse of points which can be accomplished by multiplying by negative 1 or negation. – dting May 10 '11 at 17:34
3

itemgetter will throw this error up to Python2.4

If you are stuck on 2.4, you will need to use the lambda

my_list.sort(key=lambda x: (x['points'], x['time']))

It would be preferable to upgrade to a newer Python if possible

John La Rooy
  • 295,403
  • 53
  • 369
  • 502