Newbie: sort list of dictionaries

Wade Leftwich wade at lightlink.com
Tue Dec 30 17:40:42 EST 2003


Paul Rubin <http://phr.cx@NOSPAM.invalid> wrote in message news:<7xy8su7a1k.fsf at ruckus.brouhaha.com>...
> Sven Brandt <no_more_spam at no_use_for.me> writes:
> > I have a list of dictionaries. I want the elements of the list to be
> > sorted by the value of a key of the dict .
> > 
> > Excample:
> > my_list=[{'title': 'foo', 'id': 5, 'text': 'some text'},
> >           {'title': 'bar', 'id': 3, 'text': 'my text'},
> >           {'title': 'bla', 'id': 6, 'text': 'any text'}, ]
> > 
> > my_list.sort("by the id value")
> 
> The Pythonic way to do it may not be what you're used to, but once you
> understand it you'll be able to apply the understanding to other areas
> of programming.
> 
> The list sort method lets you pass an optional comparison function,
> that takes two items and returns -1, 0, or 1, depending on what order
> the items are supposed to appear in.  The comparison function takes
> exactly two args (the items to be compared).  You can't pass a third
> arg to specify the field name.  You could do something ugly like use a
> global variable, but the preferred way given a field name is to
> construct a brand new comparison function just for that name:
> 
>     def compare_by (fieldname):
>        def compare_two_dicts (a, b):
>           return cmp(a[fieldname], b[fieldname])
>        return compare_two_dicts
> [snip ...]

Another way to do it, also Pythonic I think, is with the
Decorate-Sort-Undecorate (DSU) pattern:

unsorted_list = [{'id':99, 'title':'a'},{'id':42, 'title':'b'}, ... ] 
decorated_list = [(x['id'],x) for x in unsorted_list]
decorated_list.sort()
sorted_list = [y for (x,y) in decorated_list]

If performance is a consideration, this is supposed to be much faster
than providing a comparison function to list.sort().

If you want to package it up as a function, try this:

>>> def sortlist(L, decorator=None):
... 	if decorator is None:
... 		def decorator(x):
... 			return x
... 	newL = [(decorator(x), x) for x in L]
... 	newL.sort()
... 	L[:] = [y for (x,y) in newL]
... 	
>>> L = [2,3,6,1,17,0]
>>> sortlist(L)
>>> L
[0, 1, 2, 3, 6, 17]
>>> L = [{'id':99, 'title':'a'},{'id':42, 'title':'b'}]
>>> def mydecorator(mydict):
... 	return mydict['id']
... 
>>> sortlist(L, mydecorator)
>>> L
[{'id': 42, 'title': 'b'}, {'id': 99, 'title': 'a'}]
>>> 

Now you have in-place sorting, just like with the built-in sort()
method.

-- Wade Leftwich
Ithaca, NY




More information about the Python-list mailing list