1

I have a list within a list, and want to change all values to integers. I have accomplished this, but suppose I had the user specify how many lists within lists they will have. How can I convert all of these values into integers as well?

I have the following code which currently takes any list, or any list within a list, and converts all values to integers. I can see how I can expand on this to more lists within lists, but that may be unnecessary, or possibly not enough. And of course, this seems very slow and takes a lot of code.

for i in l:
    index = l.index(i)
    l[index] = list(map(int, l[index]))

My list is l, and each list within l is i. I take the index of whatever i is, and convert all values within it to an integer. How can I create a function/loop that takes in how many lists within lists there are, and convert them all to integers?

For example on this input:

l = [['6', '5'], '7', ['88', '99', '1']]

The above code will return:

[[6, 5], 7, [88, 99, 1]]

However, if I have:

l = [['6', '7'], ['6', ['7', '8']]]

I receive the error:

"TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'"

I understand that this is because I am only converting lists nested in lists, not lists nested in lists nested in lists, so it thinks that I am trying to convert a whole list into an integer.

Long story short, how can I build a function that can convert any number of nested lists into integers?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61

2 Answers2

12

You could use a recursive function to go one level inside every time:

def convert_rec(x):
    if isinstance(x, list):
        return list(map(convert_rec, x))
    else:
        return int(x)

Note that now you don't need to use a loop and simply call this function on the whole list. This works as expected:

>>> l = [['6', '5'], '7', ['88', '99', '1']]
>>> print(convert_rec(l))
[[6, 5], 7, [88, 99, 1]]

>>> l = [['6', '7'], ['6', ['7', '8']]]
>>> print(convert_rec(l))
[[6, 7], [6, [7, 8]]]

Note also that this code can throw an Exception when trying to convert to int, so for a more generic and easier to debug code, add try/except:

def convert_rec(x):
    if isinstance(x, list):
        return list(map(convert_rec, x))
    else:
        try:
            x = int(x)
        except ValueError as ve:
            print(ve)
        except TypeError as te:
            print(te)
        finally:
            return x
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
  • Thank you for your time and your work! Could you please explain what 'isinstance' represents? I am pretty new to python. – watwolves8855 Jul 01 '19 at 15:52
  • 1
    @watwolves8855 have a look [here](https://www.programiz.com/python-programming/methods/built-in/isinstance). In short, it checks if the first argument (the object) is an instance or subclass of the second argument. an equivalent (more or less) will be: `type(x) is list`. read [this interesting answer](https://stackoverflow.com/a/1549854/6045800) for more reference – Tomerikoo Jul 01 '19 at 17:09
1

Or maybe we could simply use a re.sub:

import re

print(eval(re.sub(r"'", "", str([['6', '5'], '7', ['88', '99', '1']]))))

Output

[[6, 5], 7, [88, 99, 1]]
Emma
  • 27,428
  • 11
  • 44
  • 69
  • 2
    I think the OP wants an actual nested list of ints. Your code produces a string. – PM 2Ring Jul 01 '19 at 05:17
  • 1
    Thank you for your answer. I'm not exactly sure what 're.sub' does. From what I can tell, it takes an argument ' "(')" ', substitutes it with nothing ' "" ', in the list in the third argument. Is that correct? Also, what is the purpose of the r after ' re.sub( '? Thanks. – watwolves8855 Jul 01 '19 at 15:56
  • 1
    Assuming the input list is `l`, you could start your code with `str(l)`, and then do `eval()` on the `sub`'s result to get a list as an input and return a list in the end – Tomerikoo Jul 01 '19 at 17:18