How to sort alpha numeric set in python

I have a set

set(['booklet', '4 sheets', '48 sheets', '12 sheets'])

After sorting I want it to look like

4 sheets,
12 sheets,
48 sheets,
booklet

Any idea please


Solution 1:

Jeff Atwood talks about natural sort and gives an example of one way to do it in Python. Here is my variation on it:

import re 

def sorted_nicely( l ): 
    """ Sort the given iterable in the way that humans expect.""" 
    convert = lambda text: int(text) if text.isdigit() else text 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key)

Use like this:

s = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
for x in sorted_nicely(s):
    print(x)

Output:

4 sheets
12 sheets
48 sheets
booklet

One advantage of this method is that it doesn't just work when the strings are separated by spaces. It will also work for other separators such as the period in version numbers (for example 1.9.1 comes before 1.10.0).

Solution 2:

Short and sweet:

sorted(data, key=lambda item: (int(item.partition(' ')[0])
                               if item[0].isdigit() else float('inf'), item))

This version:

  • Works in Python 2 and Python 3, because:
    • It does not assume you compare strings and integers (which won't work in Python 3)
    • It doesn't use the cmp parameter to sorted (which doesn't exist in Python 3)
  • Will sort on the string part if the quantities are equal

If you want printed output exactly as described in your example, then:

data = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
r = sorted(data, key=lambda item: (int(item.partition(' ')[0])
                                   if item[0].isdigit() else float('inf'), item))
print ',\n'.join(r)