Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert string in list of lists to float in place?

my_list=[['A','B','C','0.0'],['D','E','F','1.0'],['G','H','I','0'],['J','K','L','M']

I've tried doing

new_list=[[float(x) for x in i if x.isnumeric()] for i in my_list]

Output

[[0.0],[1.0],[0],[]]

Expected output

[['A','B','C',0.0],['D','E','F',1.0],['G','H','I',0],['J','K','L','M']

I don't know how to turn the final values into a float and modify the values in place, I've tried appending. I've tried the answers to other questions too but they created a new list, but I want to change the original list.

EDIT Changed my list to include decimals. The below answers worked if the numbers (string) were '0' but not decimals '0.0' or '1.0'.

like image 896
catzen Avatar asked Jan 25 '23 19:01

catzen


2 Answers

You need to keep x if x is not numeric. You are close:

>>> my_list = [['A','B','C','0'], ['D','E','F','1'], ['G','H','I','J']]
>>> new_list = [[float(x) if x.isnumeric() else x for x in i] for i in my_list]
>>> new_list
[['A', 'B', 'C', 0.0], ['D', 'E', 'F', 1.0], ['G', 'H', 'I', 'J']]

Note the if x.isnumeric() else x inside the list comprehension, and that it's at the beginning of the comprehension, not the end (since it's a ternary conditional)


As you've noticed, this is creating a new list, not modifying the original. If you want to keep the original list, a basic for-loop would be better:

for i, sublist in enumerate(my_list):
    for j, x in enumerate(sublist):
        try:
            my_list[i][j] = float(x)
        except ValueError:
            pass

[['A', 'B', 'C', 0.0], ['D', 'E', 'F', 1.0], ['G', 'H', 'I', 'J']]
like image 55
TerryA Avatar answered Jan 30 '23 01:01

TerryA


Assign to my_list[:] to modify it inplace. Use a ternary if instead of the comprehensions if filter to keep all items.

#       v modify list instead of replacing it
my_list[:] = [[float(x) if x.isnumeric() else x for x in i] for i in my_list]
#                       ^ ternary if provides a value for each element

If the nested lists must be modified in-place, consider using a loop to explicitly access each sub-list. If memory consumption is a goal, use a generator expression ((...)) instead of a list comprehension ([...]) for the new elements.

for sub_list in my_list:
    sub_list[:] = (float(x) if x.isnumeric() else x for x in sub_list)

To convert all float values, not just those that are purely digits, use try-except. str.isnumeric will for example reject '12.3'.

def try_float(literal: str):
    try:
        return float(literal)
    except ValueError:
        return literal

for sub_list in my_list:
    sub_list[:] = (try_float(x) for x in sub_list)
like image 22
MisterMiyagi Avatar answered Jan 30 '23 01:01

MisterMiyagi