Como converter seqüências de caracteres em números inteiros em Python?

438

Eu tenho uma tupla de tuplas de uma consulta MySQL como esta:

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

Gostaria de converter todos os elementos da string em números inteiros e colocá-los novamente em uma lista de listas:

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

Tentei alcançá-lo, evalmas ainda não obtive nenhum resultado decente.

elfuego1
fonte
2
Talvez considere um módulo adaptador de banco de dados diferente? Eu sei que os módulos adaptadores do PostgreSQL retornarão resultados como o seu conjunto T2.
kquinn
3
Possível duplicado da Parse String para Float ou Int
Nathan
observe: ao usar o mapa, você obterá uma lista de objetos de mapa nos python 3 e 3.5. Isso acontece no Python 3.5, como mencionado acima. new_list = list (list (int (a) para a em b) para b em T1 se a.isdigit ())
Convidado
Pergunta semelhante para uma lista não-aninhada: Converter todas as cordas em uma lista para int
Aran-Fey

Respostas:

630

int()é a função interna padrão do Python para converter uma string em um valor inteiro. Você o chama com uma sequência que contém um número como argumento e retorna o número convertido em um número inteiro:

print (int("1") + 1)

As impressões acima 2.

Se você conhece a estrutura da sua lista, T1 (que simplesmente contém listas, apenas um nível), você pode fazer isso no Python 2:

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

No Python 3:

T2 = [list(map(int, x)) for x in T1]
descontrair
fonte
4
por que não T2 = map(lambda lol: map(int, lol), T1)? Compreensões de mapas ou listas, ambas são bobagens;)
flying sheep o
4
@flyingsheep Mapa duplo parece bobagem para mim, isso parece ótimo.
Jamylak # 26/12
Que tal remover o exemplo do Python 2 (por causa do fim da vida útil do Python2)?
precisa
28

Você pode fazer isso com uma compreensão da lista:

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

A lista interna compreensão ( [int(column) for column in row]) constrói a listde ints a partir de uma sequência de intobjetos -able, como seqüências de caracteres decimais, em row. A compreensão da lista externa ( [... for row in T1])) cria uma lista dos resultados da compreensão da lista interna aplicada a cada item no T1.

O trecho de código falhará se alguma das linhas contiver objetos que não podem ser convertidos int. Você precisará de uma função mais inteligente se desejar processar linhas que contenham cadeias não decimais.

Se você conhece a estrutura das linhas, pode substituir a compreensão da lista interna por uma chamada para uma função da linha. Por exemplo.

T2 = [parse_a_row_of_T1(row) for row in T1]
Will Harris
fonte
16

Prefiro usar apenas listas de compreensão:

[[int(y) for y in x] for x in T1]
odwl
fonte
12

Em vez de colocar int( ), coloque o float( )que permitirá que você use decimais junto com números inteiros.

weir99
fonte
2
Você pode explicar mais detalhes sobre a sua resposta?
Rico
10

Eu concordo com as respostas de todos até agora, mas o problema é que, se você não tiver todos os números inteiros, eles travarão.

Se você deseja excluir não-inteiros,

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())

Isso gera apenas dígitos reais. A razão de eu não usar a compreensão direta da lista é porque a compreensão da lista vaza suas variáveis ​​internas.

Christian Witts
fonte
2
isdigité complicado, experimente -1. int(<str>)é a maneira de verificar por try/ except.
21416
9
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
P.Hunter
fonte
7
Bem-vindo ao Stack Overflow! Em vez de publicar apenas um bloco de código, explique por que esse código resolve o problema apresentado. Sem uma explicação, isso não é uma resposta.
Artemix 26/11/2012
7

Tente isso.

x = "1"

x é uma string porque possui aspas, mas possui um número.

x = int(x)

Como x tem o número 1, posso transformá-lo em um número inteiro.

Para ver se uma sequência é um número, você pode fazer isso.

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)

Ele deve ser impresso em IDLE True porque x é um número.

y_test = is_number(y)

print(y_test)

Ele deve ser impresso em IDLE False porque y não é um número.

TheRedstoneLemon
fonte
2
Sua função is_number está incorreta. '1' não é igual a 1. Este não é Perl. :-P
Veky
3
Não reinvente a roda, use x.isnumeric().
bfontaine
4

Usando compreensão de lista:

t2 = [map(int, list(l)) for l in t1]
Jon
fonte
1
no python 3, isso retorna uma lista de objetos de mapa :(
CpILL 15/15
3

No Python 3.5.1, coisas como estas funcionam:

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

e

Enter number:  4.7
4
5

George.

George Moraitis
fonte
3

Veja esta função

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

Então

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

Você também pode verificar

if val == None:  # True if input value can not be converted
    pass  # Note: Don't use 'if not val:'
Shameem
fonte
evalé mau: você deve substituí-lo por ast.literal_eval.
Eli Korvigo
3

Outra solução funcional para o Python 2:

from functools import partial

map(partial(map, int), T1)

O Python 3 ficará um pouco confuso:

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

podemos consertar isso com um invólucro

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

oldmap(partial(oldmap, int), T1)
Eli Korvigo
fonte
1

Se for apenas uma tupla, algo como rows=[map(int, row) for row in rows]fará o truque. (Existe uma compreensão da lista e uma chamada para mapear (f, lst), que é igual a [f (a) para a in lst], lá.)

Eval não é o que você deseja fazer, caso haja algo como __import__("os").unlink("importantsystemfile")no seu banco de dados por algum motivo. Sempre valide sua entrada (se não houver mais nada, a exceção int () aumentará se você tiver uma entrada incorreta).

AKX
fonte
-1

Você pode fazer algo assim:

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)  
Amit Rawat
fonte
-1

Quero compartilhar uma opção disponível que ainda não parece ser mencionada aqui:

rumpy.random.permutation(x)

Irá gerar uma permutação aleatória da matriz x. Não é exatamente o que você pediu, mas é uma solução potencial para perguntas semelhantes.

samvoit4
fonte