7

I'm trying to sort a list alphabetically, where capital letters should come before lower case letters.

l = ['a', 'b', 'B', 'A']

sorted(l) should result in ['A','a','B','b']

I've tried these two forms, but to no avail;

>>> sorted(l, key=lambda s: s.lower())
['a', 'A', 'b', 'B']
>>> sorted(l, key=str.lower)
['a', 'A', 'b', 'B']
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
user2388809
  • 115
  • 2
  • 4

2 Answers2

15

Create a tuple as your key instead:

>>> sorted(lst, key=lambda L: (L.lower(), L))
['A', 'a', 'B', 'b']

This means the sort order for lower-case doesn't change ('a', 'a') but means the first key for upper case puts it level with the lower-case equivalent, then sorts before it: eg ('a', 'A') < ('a', 'a')

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • Perfect solution. Sorry about my braindead previous comment :) – Tim Pietzcker May 16 '13 at 08:00
  • If you have non-english strings, be very careful of methods that rely on using `.lower()` for case insensitive sort, they work only for the ASCII subset of characters. The proper way involves a bit of fiddling around with locale settings. – wim May 16 '13 at 08:07
  • For example, this solution does not work for `lst = ['á', 'b', 'B', 'Á']` on python 2 (probably it will on python3) – wim May 16 '13 at 08:09
  • @Wim on Py2... `['a', 'B', 'b', '\xc3\x81']` on 3.3: `['B', 'b', 'Á', 'á']` – Jon Clements May 16 '13 at 08:15
  • only using regular letter characters btw: [a-z] and [A-Z] – user2388809 May 16 '13 at 08:29
5

Interesting how such a list supposed to sort following list

lst = ['abb', 'ABB', 'aBa', 'AbA']

Proposed solution produce following result

>>> sorted(lst, key=lambda L: (L.lower(), L))
['AbA', 'aBa', 'ABB', 'abb']

I can propose more complicated solution with different result

>>> sorted(lst, key=lambda a: sum(([a[:i].lower(), 
                                    a[:i]] for i in range(1, len(a)+1)),[]))
['ABB', 'AbA', 'aBa', 'abb']
oleg
  • 4,082
  • 16
  • 16
  • 2
    Good idea, but the expression could be simpler -- how about `[ord(x)+31.5*x.isupper() for x in a]`? – georg May 16 '13 at 09:35