user248237
user248237

Reputation:

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", "-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?

Upvotes: 14

Views: 8682

Answers (7)

Chillar Anand
Chillar Anand

Reputation: 29514

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]

Upvotes: 4

denis
denis

Reputation: 21947

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

Upvotes: 0

Escualo
Escualo

Reputation: 42082

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.

Upvotes: 0

msw
msw

Reputation: 43487

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]

Upvotes: 1

Ryan
Ryan

Reputation: 15326

Without using evaluation:

def convert(val):
    constructors = [int, float, str]
    for c in constructors:
        try:
            return c(val)
        except ValueError:
            pass

Upvotes: 8

jemfinch
jemfinch

Reputation: 2889

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.

Upvotes: 3

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798606

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]

Upvotes: 25

Related Questions