Python, Determine If A String Should Be Converted Into Int Or Float
I want to convert a string to the tightest possible datatype: int or float. I have two strings: value1='0.80' #this needs to be a float value2='1.00' #this needs to be an i
Solution 1:
def isfloat(x):
try:
a = float(x)
except (TypeError, ValueError):
return False
else:
return True
def isint(x):
try:
a = float(x)
b = int(a)
except (TypeError, ValueError):
return False
else:
return a == b
Solution 2:
Python float
objects have an is_integer
method:
from ast import literal_eval
def parses_to_integer(s):
val = literal_eval(s)
return isinstance(val, int) or (isinstance(val, float) and val.is_integer())
Solution 3:
def coerce(x):
try:
a = float(x)
b = int(x)
if a != b:
return a
else:
return b
except:
raise ValueError("failed to coerce str to int or float")
Solution 4:
I had to handle the case of ensuring that '1.0' gets converted to '1' when I was trying to determine the differences between two XML documents. So I wrote this function to help me. I also think that some of the other solutions will fail when the string literal in question is 'True' or 'False'. At any rate this function works very well for me. I hope that it will help you too.
from ast import literal_eval
def convertString(s):
'''
This function will try to convert a string literal to a number or a bool
such that '1.0' and '1' will both return 1.
The point of this is to ensure that '1.0' and '1' return as int(1) and that
'False' and 'True' are returned as bools not numbers.
This is useful for generating text that may contain numbers for diff
purposes. For example you may want to dump two XML documents to text files
then do a diff. In this case you would want <blah value='1.0'/> to match
<blah value='1'/>.
The solution for me is to convert the 1.0 to 1 so that diff doesn't see a
difference.
If s doesn't evaluate to a literal then s will simply be returned UNLESS the
literal is a float with no fractional part. (i.e. 1.0 will become 1)
If s evaluates to float or a float literal (i.e. '1.1') then a float will be
returned if and only if the float has no fractional part.
if s evaluates as a valid literal then the literal will be returned. (e.g.
'1' will become 1 and 'False' will become False)
'''
if isinstance(s, str):
# It's a string. Does it represnt a literal?
#
try:
val = literal_eval(s)
except:
# s doesn't represnt any sort of literal so no conversion will be
# done.
#
val = s
else:
# It's already something other than a string
#
val = s
##
# Is the float actually an int? (i.e. is the float 1.0 ?)
#
if isinstance(val, float):
if val.is_integer():
return int(val)
# It really is a float
return val
return val
The output of the unit test of this function produces:
convertString("1")=1; we expect 1
convertString("1.0")=1; we expect 1
convertString("1.1")=1.1; we expect 1.1
convertString("010")=8; we expect 8
convertString("0xDEADBEEF")=3735928559; we expect 3735928559
convertString("hello")="hello"; we expect "hello"
convertString("false")="false"; we expect "false"
convertString("true")="true"; we expect "true"
convertString("False")=False; we expect False
convertString("True")=True; we expect True
convertString(sri.gui3.xmlSamples.test_convertString.A)=sri.gui3.xmlSamples.test_convertString.A; we expect sri.gui3.xmlSamples.test_convertString.A
convertString(<function B at 0x7fd9e2f27ed8>)=<function B at 0x7fd9e2f27ed8>; we expect <function B at 0x7fd9e2f27ed8>
convertString(1)=1; we expect 1
convertString(1.0)=1; we expect 1
convertString(1.1)=1.1; we expect 1.1
convertString(3735928559)=3735928559; we expect 3735928559
convertString(False)=False; we expect False
convertString(True)=True; we expect True
The unit test code follows:
import unittest
# just class for testing that the class gets returned unmolested.
#
class A: pass
# Just a function
#
def B(): pass
class Test(unittest.TestCase):
def setUp(self):
self.conversions = [
# input | expected
('1' ,1 ),
('1.0' ,1 ), # float with no fractional part
('1.1' ,1.1 ),
('010' ,8 ), # octal
('0xDEADBEEF',0xDEADBEEF), # hex
('hello' ,'hello' ),
('false' ,'false' ),
('true' ,'true' ),
('False' ,False ), # bool
('True' ,True ), # bool
(A ,A ), # class
(B ,B ), # function
(1 ,1 ),
(1.0 ,1 ), # float with no fractional part
(1.1 ,1.1 ),
(0xDEADBEEF ,0xDEADBEEF),
(False ,False ),
(True ,True ),
]
def testName(self):
for s,expected in self.conversions:
rval = convertString(s)
print 'convertString({s})={rval}; we expect {expected}'.format(**locals())
self.assertEqual(rval, expected)
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()
Solution 5:
Another way to do this, is by using regex like this:
import re
def parse_str(num):
"""
Parse a string that is expected to contain a number.
:param num: str. the number in string.
:return: float or int. Parsed num.
"""
if not isinstance(num, str): # optional - check type
raise TypeError('num should be a str. Got {}.'.format(type(num)))
if re.compile('^\s*\d+\s*$').search(num):
return int(num)
if re.compile('^\s*(\d*\.\d+)|(\d+\.\d*)\s*$').search(num):
return float(num)
raise ValueError('num is not a number. Got {}.'.format(num)) # optional
Notes on Regex Pattern
^ beginning of string
$ end of string
\s* none or more spaces
\d+ one or many digits
\d* none or many digits
\. literal dot
| or
Test
print(parse_str('1'))
print(parse_str('999'))
print(parse_str('1.2'))
print(parse_str('.3'))
print(parse_str('4.'))
print(parse_str('12.34'))
print(parse_str(' 0.5 '))
print(parse_str('XYZ'))
Result
1
999
1.2
0.3
4.0
12.34
0.5
ValueError: num is not a number. Got XYZ.
Post a Comment for "Python, Determine If A String Should Be Converted Into Int Or Float"