Discussion:
Sort list of dictionaries by key (case insensitive)
Nico Grubert
2010-01-13 07:45:41 UTC
Permalink
Hi there

I have the following list 'mylist' that contains some dictionaries:

mylist = [{'title':'the Fog', 'id':1},
{'title':'The Storm', 'id':2},
{'title':'the bible', 'id':3},
{'title':'The thunder', 'id':4}
]

How I can sort (case insensitive) the list by the dictioary's 'title' key?

The result should be this list:
[{'title':'the bible', 'id':3},
{'title':'the Fog', 'id':1},
{'title':'The Storm', 'id':2},
{'title':'The thunder', 'id':4}
]

I am using Python 2.4.


Regards,
Nico
Chris Rebert
2010-01-13 10:41:25 UTC
Permalink
Post by Nico Grubert
Hi there
mylist = [{'title':'the Fog', 'id':1},
? ? ? ? ?{'title':'The Storm', 'id':2},
? ? ? ? ?{'title':'the bible', 'id':3},
? ? ? ? ?{'title':'The thunder', 'id':4}
? ? ? ? ]
mylist.sort(key = lambda d: d['title'])

Use operator.itemgetter() to optimize in the unlikely event it becomes
necessary.

Cheers,
Chris
--
http://blog.rebertia.com
Chris Rebert
2010-01-13 11:13:30 UTC
Permalink
Post by Chris Rebert
Post by Nico Grubert
Hi there
mylist = [{'title':'the Fog', 'id':1},
? ? ? ? ?{'title':'The Storm', 'id':2},
? ? ? ? ?{'title':'the bible', 'id':3},
? ? ? ? ?{'title':'The thunder', 'id':4}
? ? ? ? ]
mylist.sort(key = lambda d: d['title'])
Er, that should have been mylist.sort(key = lambda d:
d['title'].lower()) of course.
<Goes for more coffee>

Cheers,
Chris
Nico Grubert
2010-01-13 12:09:01 UTC
Permalink
Post by Chris Rebert
d['title'].lower()) of course.
Thanks a lot for the tip, chris.
Unfortunately, I only have Python 2.3.5 installed and can't upgrade to
2.4 due to an underliying application server.

In python 2.3 the 'sort()' function does not excepts any keywords
arguments (TypeError: sort() takes no keyword arguments), so is there a
workaround?

Regards
Nico
Peter Otten
2010-01-13 12:25:24 UTC
Permalink
Post by Nico Grubert
Post by Chris Rebert
d['title'].lower()) of course.
Thanks a lot for the tip, chris.
Unfortunately, I only have Python 2.3.5 installed and can't upgrade to
2.4 due to an underliying application server.
In python 2.3 the 'sort()' function does not excepts any keywords
arguments (TypeError: sort() takes no keyword arguments), so is there a
workaround?
... decorated = [(key(item), index, item) for index, item in
enumerate(items)]
... decorated.sort()
... return [item[2] for item in decorated]
...
Post by Nico Grubert
Post by Chris Rebert
items = "Atem ?ther ?hnlich anders".split()
print " ".join(sorted(items, key=lambda s: s.lower()))
anders Atem ?ther ?hnlich
Post by Nico Grubert
Post by Chris Rebert
print " ".join(sorted(items, key=lambda s: locale.strxfrm(s)))
?hnlich anders Atem ?ther

The above may run on 2.3, but I actually ran it on 2.6.

Peter
Stefan Behnel
2010-01-13 12:35:14 UTC
Permalink
items = "Atem ?ther ?hnlich anders".split()
print " ".join(sorted(items, key=lambda s: s.lower()))
If you can make sure that 's' is either always a byte string or always a
unicode string (which is good programming practice anyway), an unbound
method can simplify (and speed up) the above, e.g.

sorted(items, key=unicode.lower)

Stefan
Peter Otten
2010-01-13 11:05:04 UTC
Permalink
Post by Nico Grubert
mylist = [{'title':'the Fog', 'id':1},
{'title':'The Storm', 'id':2},
{'title':'the bible', 'id':3},
{'title':'The thunder', 'id':4}
]
How I can sort (case insensitive) the list by the dictioary's 'title' key?
[{'title':'the bible', 'id':3},
{'title':'the Fog', 'id':1},
{'title':'The Storm', 'id':2},
{'title':'The thunder', 'id':4}
]
I am using Python 2.4.
Python 2.4.6 (#2, Mar 19 2009, 10:02:47)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Post by Nico Grubert
import locale
locale.setlocale(locale.LC_ALL, "")
'de_DE.UTF-8'
Post by Nico Grubert
mylist = [{'title':'the Fog', 'id':1},
... {'title':'The Storm', 'id':2},
... {'title':'the bible', 'id':3},
... {'title':'The thunder', 'id':4}
... ]
Post by Nico Grubert
mylist.sort(key=lambda item: locale.strxfrm(item["title"]))
import pprint
pprint.pprint(mylist)
[{'id': 3, 'title': 'the bible'},
{'id': 1, 'title': 'the Fog'},
{'id': 2, 'title': 'The Storm'},
{'id': 4, 'title': 'The thunder'}]

Peter
Florian Diesch
2010-01-13 11:11:08 UTC
Permalink
Post by Nico Grubert
Hi there
mylist = [{'title':'the Fog', 'id':1},
{'title':'The Storm', 'id':2},
{'title':'the bible', 'id':3},
{'title':'The thunder', 'id':4}
]
How I can sort (case insensitive) the list by the dictioary's 'title' key?
mylist.sort(key=lambda x: x['title'].lower())



Florian
--
<http://www.florian-diesch.de/software/easygconf/>
Nico Grubert
2010-01-13 15:18:23 UTC
Permalink
Thanks a lot Stefan & Peter.

I'm almost there (except sorting of umlauts does not work yet).


import locale

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?


Regards
Nico
Stefan Behnel
2010-01-13 15:26:42 UTC
Permalink
Post by Nico Grubert
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?
http://wiki.python.org/moin/HowTo/Sorting#Topicstobecovered

Stefan
Peter Otten
2010-01-13 15:37:27 UTC
Permalink
Post by Nico Grubert
Thanks a lot Stefan & Peter.
I'm almost there (except sorting of umlauts does not work yet).
import locale
locale.setlocale(locale.LC_ALL, "")
Post by Nico Grubert
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
Nico Grubert
2010-01-14 06:49:33 UTC
Permalink
Post by Stefan Behnel
http://wiki.python.org/moin/HowTo/Sorting#Topicstobecovered
Works fine. Thanks a lot for your help, Stefan.

Regards
Nico

Loading...