tags:

views:

783

answers:

10

I'm looking for a way to convert numbers to string format, dropping any redundant '.0'

The input data is a mix of floats and strings. Desired output:

0 --> '0'

0.0 --> '0'

0.1 --> '0.1'

1.0 --> '1'

I've come up with the following generator expression, but I wonder if there's a faster way:

(str(i).rstrip('.0') if i else '0' for i in lst)

The truth check is there to prevent 0 from becoming an empty string.

EDIT: The more or less acceptable solution I have for now is this:

('%d'%i if i == int(i) else '%s'%i for i in lst)

It just seems strange that there is no elegant way to handle this (fairly straightforward) case in python.

A: 

Using Python's string formatting (use str.format() with Python 3.0):

from decimal import Decimal

def format_number(i):
    return '%g' % (Decimal(str(i)))
Daniel
You would better use Decimal(str(i)), or you will end up with an exception if i is a float.
Federico Ramponi
+3  A: 
def floatstrip(x):
    if x == int(x):
        return str(int(x))
    else:
        return str(x)

Be aware, though, that Python represents 0.1 as an imprecise float, on my system 0.10000000000000001 .

J.T. Hurley
Thanks, I might end up using the int check, though i would have preferred avoiding it.
Algorias
+2  A: 
from decimal import Decimal
'%g' % (Decimal(str(x)))
Andy Hume
This will yield 123457 for 123456.7 which I don't think is what the OP wants.
Robert Gamble
+2  A: 

rstrip doesn't do what you want it to do, it strips any of the characters you give it and not a suffix:

>>> '30000.0'.rstrip('.0')
'3'

Actually, just '%g' % i will do what you want. EDIT: as Robert pointed out in his comment this won't work for large numbers since it uses the default precision of %g which is 6 significant digits.

Since str(i) uses 12 significant digits, I think this will work:

>>> numbers = [ 0.0, 1.0, 0.1, 123456.7 ]
>>> ['%.12g' % n for n in numbers]
['1', '0', '0.1', '123456.7']
dF
%g is not the right way to accomplish this: >>> "%g" % 123456.7 # => '123457'.
Robert Gamble
So I need to replace rstrip('.0') with rstrip('0').rstrip('.'), which I think will be very slow.There are more pitfalls with the '%g' operator:>>> "%.20g" % 123456.7 # ==>'123456.69999999999709'
Algorias
@Algorias: not really a pitfall, you're getting the value of the best representation of 123456.7 as a Python double. To get the same as str(x), use "%.12g".
dF
A: 
>>> '%g' % 0
'0'
>>> '%g' % 0.0
'0'
>>> '%g' % 0.1
'0.1'
>>> '%g' % 1.0
'1'
Coady
>>> "%g" % 123456.7 # => '123457'.
Robert Gamble
>>> "%g" % 1234567.7 =>'1.23457e+06'
Aaron Maenpaa
A: 

Us the 0 prcision and add a period if you want one. EG "%.0f."

>>> print "%.0f."%1.0
1.
>>>
Charlie Martin
This doesn't do what the OP asked for: "%.0f." % 0.1 # => 0., instead of 0.1.
Robert Gamble
+4  A: 
(str(i)[-2:] == '.0' and str(i)[:-2] or str(i) for i in ...)
Mike Samuel
+1  A: 

If you only care about 1 decimal place of precision (as in your examples), you can just do:

("%.1f" % i).replace(".0", "")

This will convert the number to a string with 1 decimal place and then remove it if it is a zero:

>>> ("%.1f" % 0).replace(".0", "")
'0'
>>> ("%.1f" % 0.0).replace(".0", "")
'0'
>>> ("%.1f" % 0.1).replace(".0", "")
'0.1'
>>> ("%.1f" % 1.0).replace(".0", "")
'1'
>>> ("%.1f" % 3000.0).replace(".0", "")
'3000'
>>> ("%.1f" % 1.0000001).replace(".0", "")
'1'
Robert Gamble
Why the down-vote for this?
Robert Gamble
Sorry I didn't make it clear, I need to keep precision beyond 1 digit.
Algorias
Nice. Down-vote someone for *your* lack of clarity.
Matthew Schinckel
A: 
>>> x = '1.0'
>>> int(float(x))
1
>>> x = 1
>>> int(float(x))
1
sli
A: 
str(x)[-2:] == '.0' and int(x) or x
Stew