Sorting accented names that start either with lowercase or uppercase

Viewed 60

I am looking to sort the following list which contains names written in different ways:

l=['André','Gerald','Nicole','François','Fraçois','andré']

The expected result is:

['André', 'andré', 'Fraçois', 'François' 'Gerald', 'Nicole']

However, I am could not obtain it. Until now, I have tried to do a double sorting with the sorted command:

l=sorted(sorted(l, key=str.casefold), key=unidecode.unidecode)

But my result is not quite what I am looking for:

['André', 'Fraçois', 'François', 'Gerald', 'Nicole', 'andré']

Do you guys know any other command that could bring me the correct sorting?

3 Answers

This should work:

import unidecode
l = ['André','Gerald','Nicole','François','Fraçois','andré']

l = sorted(l, key=lambda s: unidecode.unidecode(s).lower())

Result:

['André', 'andré', 'Fraçois', 'François', 'Gerald', 'Nicole']

Python sort is stable, therefore a nested sort would actually work.

You could use normalize from unicodedata to remove de diacritic marks:

import unicodedata

l=['André','Gerald','Nicole','François','Fraçois','andré']

sl = sorted(l,key=lambda n:unicodedata.normalize("NFD",n).lower())

print(sl)
# ['André', 'andré', 'Fraçois', 'François', 'Gerald', 'Nicole']

If the only problem is case sensitivity, then flatten the case (only) for sorting:

>>> sorted(l, key= lambda x : x.lower())
['André', 'andré', 'François', 'Fraçois', 'Gerald', 'Nicole']

If you do not like the case-insensitive Unicode ordering that this produces, i.e. if you really want to throw unidecode into the mix, fold it together into the sort key function... that's @JLam's answer, so I won't steal their thunder.

Related