This answer is basically copy/pasted from the examples section of natsort
's documentation. All I have done is change the specifics.
>>> import re
>>> import natsort
>>>
>>> # Define how each unit will be transformed
>>> conversion_mapping = {
... "k": 1000, # kilo
... "M": 1000000, # mega
... # Extend suffixes as you need
... }
>>>
>>> # This regular expression searches for numbers and units
>>> all_units = "|".join(conversion_mapping.keys())
>>> float_re = natsort.numeric_regex_chooser(natsort.FLOAT | natsort.SIGNED)
>>> unit_finder = re.compile(r"({})({})".format(float_re, all_units), re.IGNORECASE)
>>>
>>> def unit_replacer(matchobj):
... """
... Given a regex match object, return a replacement string where units are modified
... """
... number = matchobj.group(1)
... unit = matchobj.group(2)
... new_number = float(number) * conversion_mapping[unit]
... return "{}".format(new_number)
...
>>> # Demo time!
>>> data = ['default.smt',
... 'Setup 19k Hz.smt',
... 'Setup 1k Hz.smt',
... 'Setup 3 Hz.smt',
... 'Setup 500 Hz.smt',
... 'Setup 55 Hz.smt',
... 'Setup 5k Hz.smt',
... 'Setup 9k Hz.smt']
>>> [unit_finder.sub(unit_replacer, x) for x in data]
['default.smt',
'Setup 19000.0 Hz.smt',
'Setup 1000.0 Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5000.0 Hz.smt',
'Setup 9000.0 Hz.smt']
>>>
>>> natsort.natsorted(data, key=lambda x: unit_finder.sub(unit_replacer, x), alg=natsort.LOWERCASEFIRST)
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
The advantage here is that not only does this use natsort
's robust algorithm, but you also get to use natsort
's regular expression definition of floats, which is very thorough.
Full disclosure, I am the natsort author.