How to convert list of strings to their correct Python types?
Given a list of python strings, how can I automatically convert them to their correct type?
Meaning, if I have:
["hello", "3", "3.64", &q开发者_开发百科uot;-1"]
I'd like this to be converted to the list
["hello", 3, 3.64, -1]
where the first element is a string, the second an int, the third a float, and the fourth an int.
How can I do this?
import ast
L = ["hello", "3", "3.64", "-1"]
def tryeval(val):
try:
val = ast.literal_eval(val)
except ValueError:
pass
return val
print [tryeval(x) for x in L]
Without using evaluation:
def convert(val):
constructors = [int, float, str]
for c in constructors:
try:
return c(val)
except ValueError:
pass
I accomplished the same using json.loads
method
def f(l):
for i in l:
try:
yield json.loads(i)
except:
yield i
Test:
In [40]: l
Out[40]: ['hello', '3', '3.64', '-1']
In [41]: list(f(l))
Out[41]: ['hello', 3, 3.64, -1]
def tryEval(s):
try:
return eval(s, {}, {})
except:
return s
map(tryEval, ["hello", "3", "3.64", "-1"])
Only do this if you trust the input. Also, be aware that it supports more than just literals; arithmetic expressions will be evaluated as well.
If the you are truly interested in only strings, floats, and ints, I prefer the more verbose, less-evalful
def interpret_constant(c):
try:
if str(int(c)) == c: return int(c)
except ValueError:
pass
try:
if str(float(c)) == c: return float(c)
except ValueError:
return c
test_list = ["hello", "3", "3.64", "-1"]
typed_list = [interpret_constant(x) for x in test_list]
print typed_list
print [type(x) for x in typed_list]
This is not really an answer, but I wanted to point out how important this can be when you have a database of parameters with schema ID
, PAR
, VAL
. For instance:
ID PAR VAL
001 velocity '123.45'
001 name 'my_name'
001 date '18-dec-1978'
This schema is appropriate when you don't know how many parameters you need to store for a certain ID
. The disadvantage is precisely that the values in VAL
are all strings, and need to be converted to the correct data type on demand. You can do this by adding a fourth column to the schema, called TYPE
, or you can use any of the approaches proposed thus far.
Good question!
PS. The database schema is related to one of my previous questions.
A variant of ryans's nice solution, for numpy users:
def tonum( x ):
""" -> int(x) / float(x) / None / x as is """
if np.isscalar(x): # np.int8 np.float32 ...
# if isinstance( x, (int, long, float) ):
return x
try:
return int( x, 0 ) # 0: "0xhex" too
except ValueError:
try:
return float( x ) # strings nan, inf and -inf too
except ValueError:
if x == "None":
return None
return x
def numsplit( line, sep=None ):
""" line -> [nums or strings ...] """
return map( tonum, line.split( sep )) # sep None: whitespace
精彩评论