Sort list of dictionaries by key (case insensitive)

Peter Otten __peter__ at web.de
Wed Jan 13 16:37:27 CET 2010


Nico Grubert wrote:

> Thanks a lot Stefan & Peter.
> 
> I'm almost there (except sorting of umlauts does not work yet).
> 
> 
> import locale

locale.setlocale(locale.LC_ALL, "")

> def sorted(items, key):
>      decorated = [(key(item), index, item) for index, item in
>                    enumerate(items)]
>      decorated.sort()
>      return [item[2] for item in decorated]
> 
> items = [{'title':'the Ähnlich', 'id':1},
>           {'title':'The Storm', 'id':2},
>           {'title':'the bible','id':3},
>           {'title':'The thunder', 'id':4}]
> 
> print sorted(items, key=lambda d: locale.strxfrm(d.get('title')))
> 
> -> [{'id': 2, 'title': 'The Storm'}, {'id': 4, 'title': 'The thunder'},
> {'id': 3, 'title': 'the bible'}, {'id': 1, 'title': 'the \xc4hnlich'}]
> 
> 
> The entry with the umlaut is the last item in but according to german
> umlaut rules it should be the first item in the result.
> Do I have to set anything with the locale module?

Adding the setlocale() call will suffice provided your script uses the same 
encoding as your environment. If not something like

# -*- coding:utf-8 -*-
import locale

locale.setlocale(locale.LC_ALL, "")
encoding = locale.getlocale()[1]

def sorted(items, key):
     decorated = [(key(item), index, item) for index, item in
                   enumerate(items)]
     decorated.sort()
     return [item[2] for item in decorated]

# book titles use unicode
items = [{'title':u'the Ähnlich', 'id':1},
          {'title':u'The Storm', 'id':2},
          {'title':u'the bible','id':3},
          {'title':u'The thunder', 'id':4}]

def sortkey(item):
    s = item["title"].encode(encoding)
    return locale.strxfrm(s)

print sorted(items, key=sortkey)

may be a bit more robust. If your source code doesn't use UTF-8 you have to 
modify the coding declaration at the top accordingly.

Peter




More information about the Python-list mailing list