diff options
author | Marko Kreen | 2011-04-12 08:39:38 +0000 |
---|---|---|
committer | Marko Kreen | 2011-04-15 10:20:25 +0000 |
commit | 3d8bc13ec1829c530cc79285bc145bd796f8e636 (patch) | |
tree | ac44157beb0471aa3a0e6b46d956aeb21040956b | |
parent | 32862105dfa922d62c9755ea63658523ad513ee1 (diff) |
skytools.natsort: natural sorting of strings
-rw-r--r-- | python/skytools/natsort.py | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/python/skytools/natsort.py b/python/skytools/natsort.py new file mode 100644 index 00000000..059cb58c --- /dev/null +++ b/python/skytools/natsort.py @@ -0,0 +1,56 @@ +"""Natural sort. + +Compares numeric parts numerically. +""" + +# Based on idea at http://code.activestate.com/recipes/285264/ +# Works with both Python 2.x and 3.x +# Ignores leading zeroes: 001 and 01 are considered equal + +import re as _re +_rc = _re.compile(r'\d+|\D+') + +def natsort_key(s): + """Split string to numeric and non-numeric fragments.""" + return [ not f[0].isdigit() and f or int(f, 10) for f in _rc.findall(s) ] + +def natsort(lst): + """Natural in-place sort, case-sensitive.""" + lst.sort(key = natsort_key) + +def natsorted(lst): + """Return copy of list, sorted in natural order, case-sensitive. + + >>> natsorted(['ver-1.1', 'ver-1.11', '', 'ver-1.0']) + ['', 'ver-1.0', 'ver-1.1', 'ver-1.11'] + """ + lst = lst[:] + natsort(lst) + return lst + +# case-insensitive api + +def natsort_key_icase(s): + """Split string to numeric and non-numeric fragments.""" + return natsort_key(s.lower()) + +def natsort_icase(lst): + """Natural in-place sort, case-sensitive.""" + lst.sort(key = natsort_key_icase) + +def natsorted_icase(lst): + """Return copy of list, sorted in natural order, case-sensitive. + + >>> natsorted_icase(['Ver-1.1', 'vEr-1.11', '', 'veR-1.0']) + ['', 'veR-1.0', 'Ver-1.1', 'vEr-1.11'] + """ + lst = lst[:] + natsort_icase(lst) + return lst + + +# run doctest +if __name__ == '__main__': + import doctest + doctest.testmod() + |