sort order for strings of digits

Arnaud Delobelle arnodel at gmail.com
Thu Nov 1 01:59:10 CET 2012


On 31 October 2012 23:09, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> The trick is to take each string and split it into a leading number and a
> trailing alphanumeric string. Either part may be "empty". Here's a pure
> Python solution:
>
> from sys import maxsize  # use maxint in Python 2
> def split(s):
>     for i, c in enumerate(s):
>         if not c.isdigit():
>             break
>     else:  # aligned with the FOR, not the IF
>         return (int(s), '')
>     return (int(s[:i] or maxsize), s[i:])
>
> Now sort using this as a key function:
>
> py> L = ['9', '1000', 'abc2', '55', '1', 'abc', '55a', '1a']
> py> sorted(L, key=split)
> ['1', '1a', '9', '55', '55a', '1000', 'abc', 'abc2']

You don't actually need to split the string, it's enough to return a
pair consisting of the number of leading digits followed by the string
as the key. Here's an implementation using takewhile:

>>> from itertools import takewhile
>>> def prefix(s):
...     return sum(1 for c in takewhile(str.isdigit, s)) or 1000, s
...
>>> L = ['9', '1000', 'abc2', '55', '1', 'abc', '55a', '1a']
>>> sorted(L, key=prefix)
['1', '1a', '9', '55', '55a', '1000', 'abc', 'abc2']

Here's why it works:

>>> map(prefix, L)
[(1, '9'), (4, '1000'), (1000, 'abc2'), (2, '55'), (1, '1'), (1000,
'abc'), (2, '55a'), (1, '1a')]

-- 
Arnaud


More information about the Python-list mailing list