Satheesh
Satheesh

Reputation: 33

How to sort a list alphabetically by treating same letters in different case as same in python

If input is like ['z','t','Z','a','b','A','d'],then after sorting I want to get output like ['a','A','b','d','t','z','Z'] or ['A','a','b','d','t','Z','z'].

Upvotes: 0

Views: 294

Answers (3)

Tomerikoo
Tomerikoo

Reputation: 19432

You could use sorted's (or list.sort's) extra keyword - key. You can pass to key a function according to which the sort will be performed. So for example:

l = ['z','t','Z','a','b','A','d']
print(sorted(l, key=str.lower))

Gives:

['a', 'A', 'b', 'd', 't', 'z', 'Z']

Note: this will not preserve the order of lower/upper between different letters. It will preserve the order of original input.

Upvotes: 1

Mad Physicist
Mad Physicist

Reputation: 114470

There are two options on how this sorting could be done. Option 1 is stable, meaning that the order of elements is preserved regardless of case:

['A', 'b', 'a', 'B'] -> ['A', 'a', 'b', 'B']

The other option is to always put uppercase before or after lowercase:

['A', 'b', 'a', 'B'] -> ['A', 'a', 'B', 'b'] or ['a', 'A', 'b', 'B']

Both are possible with the key argument to list.sort (or the builtin sorted).

A stable sort is simply:

['A', 'b', 'a', 'B'].sort(key=str.lower)

A fully ordered sort requires you to check the original status of the letter, in addition to comparing the lowercased values:

['A', 'b', 'a', 'B'].sort(key=lambda x: (x.lower(), x.islower()))

This uses the fact that a tuples are compared lexicographically, or element-by-element. The first difference determines the order. If two letters have different values for x.lower(), they will be sorted as usual. If they have the same lowercase representation, x.islower() will be compared. Since uppercase letters will return 0 and lowercase letters return 1, lowercase letters will come after uppercase. To switch that, invert the sense of the comparison:

['A', 'b', 'a', 'B'].sort(key=lambda x: (x.lower(), not x.islower()))

OR

['A', 'b', 'a', 'B'].sort(key=lambda x: (x.lower(), x.isupper()))

OR

['A', 'b', 'a', 'B'].sort(key=lambda x: (x.lower(), -x.islower()))

etc...

Upvotes: 1

Andrej Kesely
Andrej Kesely

Reputation: 195553

This will sort always upper-case letter first:

lst = ['z','t','Z','a','b','A','d']

print(sorted(lst, key=lambda k: 2*ord(k.lower()) + k.islower()))

Prints:

['A', 'a', 'b', 'd', 't', 'Z', 'z']

EDIT Thanks to @MadPhysicist in the comments, another variant:

print(sorted(lst, key=lambda k: (k.lower(), k.islower())))

Upvotes: 4

Related Questions