4

(I use Python 2 here)

I have a list of dictionaries, say

dei = [{'name': u'Thor'}, {'name': u'Œdipus'}, {'name': u'Creon'}]

I would like to sort that list by their 'name' attribute. This is easily done so:

dei.sort(key=lambda d: d['name'])

Now, because Python’s alphabetical sorting is ASCII-driven, the result will be

[{'name': u'Creon'}, {'name': u'Thor'}, {'name': u'Œdipus'}]

while I’d like Œdipus to be between Creon and Thor.

Following this suggestion, I use PyICU’s collator.getSortKey() function (let’s rename it sortKey() for readability), which works this way on a list strings of strings:

strings.sort(key=sortKey)

My problem here: as I cannot modify the sortKey() function anyhow, how can I use it to sort a list of more complex objects (here, dictionaries) according to some attribute?

The only way I found for the moment is by extracting the values of the dictionary in a separate list, sorting it, then implementing a custom compare(a, b) function returning −1, 0 or 1 depending on the index of a and b in the separate list, and calling sort() with this compare() function:

names = sorted([d['name'] for d in dei], key=sortKey)

def compare(a, b):
    if names.index(a) < names.index(b):
        return -1
    elif names.index(a) > names.index(b):
        return 1
    else:
        return 0

results = dei.sort(key=lambda d: d['name'], cmp=compare)

which I don’t find very elegant.

2
  • 1
    The problem isn't the key. The problem is you disagree with python over the order of the alphabet. If that 'ae' symbol comes after 'c' in your language, can you just use localization? Otherwise you must provide the comparison function telling it what order to sort the alphabet. But providing your comparison function just on a few exact words seems shortsighted. Commented Aug 5, 2016 at 16:41
  • Yes, alphabetical sorting is language-dependent, that's why I want to use PyICU, which precisely implements it for any language. Commented Aug 5, 2016 at 18:47

1 Answer 1

2

You can use your own key that internally calls getSortKey with correct value:

>>> import icu
>>> dei = [{'name': u'Thor'}, {'name': u'Œdipus'}, {'name': u'Creon'}]
>>> collator = icu.Collator.createInstance()
>>> dei.sort(key=lambda x: collator.getSortKey(x['name']))
>>> dei
[{'name': 'Creon'}, {'name': 'Œdipus'}, {'name': 'Thor'}]
Sign up to request clarification or add additional context in comments.

1 Comment

Oh sh*, it… works :-o This was one of the first thing I tried, but I tried it in pdb, which for any reason wouldn't accept collator in the lambda (global name 'collator' is not defined). It took me a while before figuring out the problem was only in pdb, and I… completely forgot to test the simplest solution again. Thanks! (And shame on me!)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.