Home > Enterprise >  Casting to a string for numeric sorting
Casting to a string for numeric sorting

Time:05-03

I have a set of numbers and I need to generate a string-hash that is sortable for these numbers. The numbers can be integers or floats, for example:

-5.75E 100
-4
-1.74E-101
1.74E-101
5
9
11
52.3
5.75E 100

I think to do non-exponents for integers and floats it would be simple:

                                    # whatever the padding needs to be
>>> sorted(map(lambda x: str(x).zfill(10), [-4, 5, 52.3]))
['-000000004', '0000000005', '00000052.3']

However, what would be a more comprehensive way to generate a string-hash here that would sort properly for the above list of numbers? I am fine prepending exponents, if necessary (or converting everything to an exponent, if required), and encoding negative numbers in complement code, if that's required too.

CodePudding user response:

You can try this,

nums = sorted(map(eval, data))
nums = list(map(str, nums))
nums

Output -

['-5.75E 100', '-4', '-1.74E-101', '1.74E-101', '5', '52.3', '5.75E 100']

CodePudding user response:

Every float object has a built-in function hex() that will convert it to a hex string. That's almost enough to make a sortable string, but there are a few problems.

First, negative numbers have a leading - but positive numbers don't have anything. You need to add a leading character to positive numbers.

Second, - comes after in the sorting order. You need to replace one or the other to make the order correct.

Third, the exponent comes at the end of the string. It needs to get moved to the front of the string to make it more significant, but the sign needs to stay at the absolute front.

Fourth, the exponent is a variable number of digits. It needs to be zero filled so that it has a consistent size.

Putting it all together produces something like this:

def sortable_string(number):
    hex_num = float(number).hex()
    if not hex_num.startswith('-'):
        hex_num = ' '   hex_num
    hex_num = hex_num.replace('-', '!')
    hex_parts = hex_num.split('p')
    exponent = hex_parts[1][0]   hex_parts[1][1:].ljust(4, '0')
    return hex_parts[0][0]   exponent   hex_parts[0][1:]
  • Related