user11094200
user11094200

Reputation:

how to convert types while keeping the same list structure

So I have this list here:

[['Afghanistan', '2.66171813', '7.460143566', '0.490880072', '52.33952713', '0.427010864', '-0.106340349', '0.261178523'], ['Albania', '4.639548302', '9.373718262', '0.637698293', '69.05165863', '0.74961102', '-0.035140377', '0.457737535'], ['Algeria', '5.248912334', '9.540244102', '0.806753874', '65.69918823', '0.436670482', '-0.194670126', ''], ['Argentina', '6.039330006', '9.843519211', '0.906699121', '67.53870392', '0.831966162', '-0.186299905', '0.305430293'], ['Armenia', '4.287736416', '9.034710884', '0.697924912', '65.12568665', '0.613697052', '-0.132166177', '0.246900991'], ['Australia', '7.25703764', '10.71182728', '0.949957848', '72.78334045', '0.910550177', '0.301693261', '0.45340696']]

My aim is to loop through the list of lists and convert number string values to integers.

I tried

for li in main_li:
    for element in li:
        if element == li[0]:
            continue
        else:
            element = int(element)

My problem is how can I get this back into the same list format I had above without the numbers being strings.

Upvotes: 0

Views: 77

Answers (6)

Mykola Zotko
Mykola Zotko

Reputation: 17911

You can use a star unpacking in a listcomp:

l = [['A', '1.1', '1.2'], ['B', '2.1', '2.2']]

[[i, *map(float, j)] for i, *j in l]
# [['A', 1.1, 1.2], ['B', 2.1, 2.2]]

Upvotes: 0

agtoever
agtoever

Reputation: 1699

Most of the answers assume a fixed level of nesting (list of lists). You could (if applicable) use the following code, which uses recursion of handle deeper nested lists (lists of lists of lists, etc).

def nested_str_to_float(value):
    """ Converts an string to float. Value may be a single value, a list
        or even a nested list. If value is a (nested) list, all
        values in the (nested) list are evaluated to floats wherever possible.

        Args:
            value: single value of any type or a list

        Returns:
            a copy of value with all float-convertible items converted to float
    """

    # Test if value is a list, if so, recursively call nested_str_to_float
    if isinstance(value, list):
        return [nested_str_to_float(item) for item in value]

    # Try to convert to float; if possible, return float, else return value
    try:
        return float(value)
    except ValueError:
        return value

By the way, check this SO answer to see what Python considers floats...

Upvotes: 0

ᴀʀᴍᴀɴ
ᴀʀᴍᴀɴ

Reputation: 4538

Simply just convert those elements that are convertible to float and change them in current list with iterating through list index:

for i in range(len(main_li)):
    for j in range(len(main_li[i])):
        try:
            main_li[i][j] = float(main_li[i][j])
        except ValueError:
            continue


li # [['Afghanistan', 2.66171813, 7.460143566, 0.490880072, 52.33952713, 0.427010864, -0.106340349, 0.261178523], ['Albania', 4.639548302, 9.373718262, 0.637698293, 69.05165863, 0.74961102, -0.035140377, 0.457737535], ['Algeria', 5.248912334, 9.540244102, 0.806753874, 65.69918823, 0.436670482, -0.194670126, ''], ['Argentina', 6.039330006, 9.843519211, 0.906699121, 67.53870392, 0.831966162, -0.186299905, 0.305430293], ['Armenia', 4.287736416, 9.034710884, 0.697924912, 65.12568665, 0.613697052, -0.132166177, 0.246900991], ['Australia', 7.25703764, 10.71182728, 0.949957848, 72.78334045, 0.910550177, 0.301693261, 0.45340696]]

Upvotes: 0

bumblebee
bumblebee

Reputation: 1841

You can do it by making a small change in your code

for li in main_li:
for i in range(1,len(li)):
    try:
        li[i] = int(li[i])
    except ValueError:
        pass

Upvotes: 2

Mohit Motwani
Mohit Motwani

Reputation: 4792

Your list elements are float so you can only convert them to float:

import re
pattern = re.compile('[-+]?\d+(\.\d+)?') # a pattern for all number types
new_list = []
for nest in l:
    temp_list = []
    for val in nest:
        if bool(pattern.match(val)): #check if the element is a number
            temp_list.append(float(val))
            continue
        temp_list.append(val)
    new_list.append(temp_list)  
print(new_list)
[['Afghanistan', 2.66171813, 7.460143566, 0.490880072, 52.33952713, 0.427010864, -0.106340349, 0.261178523], ['Albania', 4.639548302, 9.373718262, 0.637698293, 69.05165863, 0.74961102, -0.035140377, 0.457737535], ['Algeria', 5.248912334, 9.540244102, 0.806753874, 65.69918823, 0.436670482, -0.194670126, ''], ['Argentina', 6.039330006, 9.843519211, 0.906699121, 67.53870392, 0.831966162, -0.186299905, 0.305430293], ['Armenia', 4.287736416, 9.034710884, 0.697924912, 65.12568665, 0.613697052, -0.132166177, 0.246900991], ['Australia', 7.25703764, 10.71182728, 0.949957848, 72.78334045, 0.910550177, 0.301693261, 0.45340696]]

Upvotes: 1

Rocky Li
Rocky Li

Reputation: 5958

You shouldn't (not saying it's not possible) change list values while you loop over them. You'll have to create a new list. Fortunately, you can do it very easily with a small modification to your original code:

newlist = []
for li in main_li:
    newli = []
    for element in li:
        if element == li[0]:
            newli.append(element)
        else:
            try:
                newli.append(int(float(element)))
            except Exception as e:
                newli.append(0) # This is added because not everything in your list can be converted to int.
    newlist.append(newli)

newlist will be your modified list of lists.

Alternatively, you can use list comprehension:

newlist = [[p[0]] + [int(float(x)) for x in p[1:]] for p in main_li]

Note how this requires all of your string to be correctly formatted.

Upvotes: 1

Related Questions