456

I have a tuple of tuples from a MySQL query like this:

T1 = (('13', '17', '18', '21', '32'),
      ('07', '11', '13', '14', '28'),
      ('01', '05', '06', '08', '15', '16'))

I'd like to convert all the string elements into integers and put them back into a list of lists:

T2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]

I tried to achieve it with eval but didn't get any decent result yet.

martineau
  • 112,593
  • 23
  • 157
  • 280
elfuego1
  • 10,218
  • 9
  • 27
  • 24
  • 2
    Perhaps consider a different database adapter module? I know the PostgreSQL adapter modules will return results like your T2 set. – kquinn Mar 13 '09 at 11:06
  • 3
    Possible duplicate of [Parse String to Float or Int](http://stackoverflow.com/questions/379906/parse-string-to-float-or-int) – Nathan Nov 18 '15 at 22:49
  • please notice: when using map, you will get a list of map objects in python 3 and 3.5. This does it for Python 3.5 as mentioned above. new_list = list(list(int(a) for a in b) for b in T1 if a.isdigit()) – Guest May 28 '17 at 20:02
  • Similar question for a non-nested list: [Convert all strings in a list to int](//stackoverflow.com/q/7368789) – Aran-Fey Oct 08 '18 at 15:32
  • Although, most of the answers accepted, I would like to add good reference here : https://www.scratchcode.io/easy-ways-to-convert-string-to-int-python/ – Mayank Dudakiya Dec 08 '20 at 04:40

15 Answers15

650

int() is the Python standard built-in function to convert a string into an integer value. You call it with a string containing a number as the argument, and it returns the number converted to an integer:

>>> int("1") + 1
2

If you know the structure of your list, T1 (that it simply contains lists, only one level), you could do this in Python 3:

T2 = [list(map(int, x)) for x in T1]

In Python 2:

T2 = [map(int, x) for x in T1]
wjandrea
  • 23,210
  • 7
  • 49
  • 68
unwind
  • 378,987
  • 63
  • 458
  • 590
  • 4
    why not `T2 = map(lambda lol: map(int, lol), T1)`? Either map or list comprehensions, both is silly ;) – flying sheep Aug 17 '11 at 17:59
  • 7
    @flyingsheep Double map seems silly to me, this seems just fine. – jamylak May 26 '12 at 12:22
  • How about removing Python 2 example (because of end of life for Python2) ? – Alisso Nov 21 '19 at 19:57
  • @flyingsheep `map(lambda)` is also silly ;) A list comprehension is more natural and easier to read. – wjandrea Sep 14 '20 at 00:54
  • 1
    @Alisso I moved it lower. Legacy Python 2 code is still in use, and anyway, don't worry about removing stuff from an answer unless it makes it significantly worse. – wjandrea Jan 04 '21 at 19:34
28

You can do this with a list comprehension:

T2 = [[int(column) for column in row] for row in T1]

The inner list comprehension ([int(column) for column in row]) builds a list of ints from a sequence of int-able objects, like decimal strings, in row. The outer list comprehension ([... for row in T1])) builds a list of the results of the inner list comprehension applied to each item in T1.

The code snippet will fail if any of the rows contain objects that can't be converted by int. You'll need a smarter function if you want to process rows containing non-decimal strings.

If you know the structure of the rows, you can replace the inner list comprehension with a call to a function of the row. Eg.

T2 = [parse_a_row_of_T1(row) for row in T1]
Will Harris
  • 21,457
  • 11
  • 63
  • 63
17

I would rather prefer using only comprehension lists:

[[int(y) for y in x] for x in T1]
odwl
  • 2,065
  • 2
  • 17
  • 15
11

Instead of putting int( ), put float( ) which will let you use decimals along with integers.

Tshilidzi Mudau
  • 6,512
  • 6
  • 35
  • 45
weir99
  • 151
  • 1
  • 2
10

I would agree with everyone’s answers so far but the problem is that if you do not have all integers, they will crash.

If you wanted to exclude non-integers then

T1 = (('13', '17', '18', '21', '32'),
      ('07', '11', '13', '14', '28'),
      ('01', '05', '06', '08', '15', '16'))
new_list = list(list(int(a) for a in b) for b in T1 if a.isdigit())

This yields only actual digits. The reason I don't use direct list comprehensions is because list comprehension leaks their internal variables.

Christian Witts
  • 10,851
  • 1
  • 31
  • 44
9

Try this.

x = "1"

x is a string because it has quotes around it, but it has a number in it.

x = int(x)

Since x has the number 1 in it, I can turn it in to a integer.

To see if a string is a number, you can do this.

def is_number(var):
    try:
        if var == int(var):
            return True
    except Exception:
        return False

x = "1"

y = "test"

x_test = is_number(x)

print(x_test)

It should print to IDLE True because x is a number.

y_test = is_number(y)

print(y_test)

It should print to IDLE False because y in not a number.

8
T3=[]

for i in range(0,len(T1)):
    T3.append([])
    for j in range(0,len(T1[i])):
        b=int(T1[i][j])
        T3[i].append(b)

print T3
Martijn Pieters
  • 963,270
  • 265
  • 3,804
  • 3,187
P.Hunter
  • 97
  • 1
  • 2
  • 8
    Welcome to Stack Overflow! Rather than only post a block of code, please explain why this code solves the problem posed. Without an explanation, this is not an answer. – Artemix Nov 26 '12 at 12:15
4

Using list comprehensions:

t2 = [map(int, list(l)) for l in t1]
Jon
  • 5,087
  • 5
  • 29
  • 38
3

Yet another functional solution for Python 2:

from functools import partial

map(partial(map, int), T1)

Python 3 will be a little bit messy though:

list(map(list, map(partial(map, int), T1)))

we can fix this with a wrapper

def oldmap(f, iterable):
    return list(map(f, iterable))

oldmap(partial(oldmap, int), T1)
Eli Korvigo
  • 9,646
  • 6
  • 46
  • 71
3

See this function

def parse_int(s):
    try:
        res = int(eval(str(s)))
        if type(res) == int:
            return res
    except:
        return

Then

val = parse_int('10')  # Return 10
val = parse_int('0')  # Return 0
val = parse_int('10.5')  # Return 10
val = parse_int('0.0')  # Return 0
val = parse_int('Ten')  # Return None

You can also check

if val == None:  # True if input value can not be converted
    pass  # Note: Don't use 'if not val:'
Shameem
  • 2,374
  • 15
  • 20
2

In Python 3.5.1 things like these work:

c = input('Enter number:')
print (int(float(c)))
print (round(float(c)))

and

Enter number:  4.7
4
5
2

Python has built in function int(string) and optional parameter base.

if your string contains an Integer value, it will convert that to the corresponding Integer value. However if you have decimnal number as string you'll need float() to convert it.

Usage:

a = '22'
b = int(a)

and

if a = '22.22'
b = int(a) '''will give error, invalid literal for int().'''
b = float(a) '''will convert the string.'''
ToM
  • 49
  • 4
1

If it's only a tuple of tuples, something like rows=[map(int, row) for row in rows] will do the trick. (There's a list comprehension and a call to map(f, lst), which is equal to [f(a) for a in lst], in there.)

Eval is not what you want to do, in case there's something like __import__("os").unlink("importantsystemfile") in your database for some reason. Always validate your input (if with nothing else, the exception int() will raise if you have bad input).

AKX
  • 123,782
  • 12
  • 99
  • 138
-1

I want to share an available option that doesn't seem to be mentioned here yet:

rumpy.random.permutation(x)

Will generate a random permutation of array x. Not exactly what you asked for, but it is a potential solution to similar questions.

Eric Aya
  • 69,000
  • 34
  • 174
  • 243
samvoit4
  • 63
  • 6
-2

You can do something like this:

T1 = (('13', '17', '18', '21', '32'),  
     ('07', '11', '13', '14', '28'),  
     ('01', '05', '06', '08', '15', '16'))  
new_list = list(list(int(a) for a in b if a.isdigit()) for b in T1)  
print(new_list)  
Patrick
  • 1,653
  • 7
  • 19
  • 28