1

If I have a list of lists that consists of str data initially, how could I alter that list to what the str represent? For example:

x = [['3.14', 'Pi and radius', '20', 'False', False', '10'],
     ['201', 'Eulers', 'True', '9.18922', 'False', '12', '90']]

to

x = [[3.14, 'Pi and radius', 20, False, False, 10],
     [201, 'Eulers', True, 9.18922, False, 12, 90]]

Where the str have been altered to float, int, bool, or kept as str, depending on what they actually are.

I think a for i in range(len(x)) loop is required, and if type(x) = ..., but I'm not sure on the specifics.

Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42
James
  • 33
  • 10
  • So you may acknowledge every good answer by upvoting it, and the best one by accepting it (click at the check mark), too. – MarianD Nov 09 '17 at 21:53

4 Answers4

2

You can use ast.literal_eval(). The code below demonstrates the usage.

import ast

values = ["hello", "1", "1.5", "False"]

def real_type(value):
    try:
        return ast.literal_eval(value)
    except:
        return value

x=[real_type(i) for i in values]
print(x)
print(x[1] + x[2])

Prints

["hello", 1, 1.5, False]
2.5

MarianD
  • 13,096
  • 12
  • 42
  • 54
Jebby
  • 1,845
  • 1
  • 12
  • 25
0

You can do like this:

define your own isdigit() function which works for float and int both because default isdigit() only works for int :

x = [['3.14', 'Pi and radius', '20', 'False', 'False', '10'],
     ['201', 'Eulers', 'True', '9.18922', 'False', '12', '90']]


def isdigit(digit):   #define your own isdigit() function which works for float and int both because default isdigit() only works for int
    try:
        float(digit)
        return 0
    except ValueError:
        return 1


check={'True':True,'False':False}  #define True , False dict

Now :

In one line solution:

list_1=[[float(sub_item) if '.' in sub_item else int(sub_item) if isdigit(sub_item) == 0 else check.get(sub_item) if sub_item == 'True' or sub_item == 'False' else sub_item for sub_item in item]for item in x]
print(list_1)

output:

[[3.14, 'Pi and radius', 20, False, False, 10], [201, 'Eulers', True, 9.18922, False, 12, 90]]

Detailed Solution:

Above list comprehension is same as :

final_list=[]   # logic is from here
for item in x:
    if isinstance(item,list):
        sub_list=[]   
        #sub_list for keep tracking of nested list in origional list
        for sub_item in item:
            if isdigit(sub_item)==0:  #passing value to isdigit() function
                if '.' in sub_item:    #float contain '.' 
                    sub_list.append(float(sub_item))
                else:                  #else it will be int
                    sub_list.append(int(sub_item))
            elif sub_item=='True' or sub_item=='False': 
                sub_list.append(check.get(sub_item))  #get value from check dict
            else:
                sub_list.append(sub_item)  #else append remaining items

        final_list.append(sub_list)

print(final_list)

output:

[[3.14, 'Pi and radius', 20, False, False, 10], [201, 'Eulers', True, 9.18922, False, 12, 90]]
Aaditya Ura
  • 12,007
  • 7
  • 50
  • 88
-1

You could define a function like convert() and in convert check the type and apply the conversion.

converted_list = [convert(i) for i in x]

or

converted_list = map(convert(),x)

convert could be something like this (requires literal_value to be imported from ast): https://stackoverflow.com/a/41475449/4040842 @ Shrewmouse

Shrewmouse's solution does not require if else statements.

spitfire21
  • 103
  • 4
-1

You are right, but instead of len() function you may use more Pythonic way with enumerate():

x = [['3.14', 'Pi and radius', '20', 'False', 'False', '10'],
     ['201', 'Eulers', 'True', '9.18922', 'False', '12', '90']]

for lst in x:
    for i, val in enumerate(lst):
        try:
            val = float(val)
            if val == int(val):
                val = int(val)
        except ValueError:
            if val == "True":
               val = True
            elif val == "False":
                val = False
        lst[i] = val


print(x)

Output:

[[3.14, 'Pi and radius', 20, False, False, 10], [201, 'Eulers', True, 9.18922, False, 12, 90]]

MarianD
  • 13,096
  • 12
  • 42
  • 54
  • Although it does the job ,this shouldn't be marked the solution. It only does the job for this particular situation. If a new type is added, the code would have to be modified. So, **0** for scalability and generality. Not nice either. No reason to downvote, but reason for upvoting other answers (Jebby's). – CristiFati Nov 09 '17 at 22:36
  • Like @ChrisFati said. This is not scalable. If your dataset contains say a dictionary, this will not handle it. My answer is scalable to any (built in at least) type. – Jebby Nov 09 '17 at 22:52