Python convierte tuple en entero

¿Hay alguna función que pueda convertir una tupla en un entero?

Ejemplo:

input = (1, 3, 7) output = 137 

 >>> reduce(lambda rst, d: rst * 10 + d, (1, 2, 3)) 123 
 >>> x = (1,3,7) >>> int(''.join(map(str,x))) 137 

Mientras que convertirlo en una cadena y luego en un int funciona, es un método un tanto intrépido. Tenemos toda la información que necesitamos para hacer un número, a saber:

  • Los digitos
  • La posición de los dígitos.

Como tenemos esta información, podemos calcular el número calculando el valor de cada unidad en cada posición, y luego multiplicándolo por el dígito en dicha posición. Luego summos los resultados y tenemos nuestro número. Esto se puede hacer en una línea así:

 test = (1, 2, 3) sum((10**pos)*val for pos, val in enumerate(reversed(test))) 

Vamos a desglosar esto:

 >>> list(enumerate(reversed(test))) [(0, 3), (1, 2), (2, 1)] 

Entonces, si lo multiplicamos:

 >>> list((10**pos)*val for pos, val in enumerate(reversed(test))) [3, 20, 100] 

Así que solo summos para obtener 123.

Edición: Una nota sobre la velocidad:

 python -m timeit "int(''.join(map(str,(1,2,3))))" 100000 loops, best of 3: 2.7 usec per loop python -m timeit 'sum((10**pos)*val for pos, val in enumerate(reversed((1,2,3))))' 100000 loops, best of 3: 2.29 usec per loop python -m timeit -s 'from functools import reduce' 'reduce(lambda rst, d: rst * 10 + d, (1, 2, 3))' 1000000 loops, best of 3: 0.598 usec per loop 

Así que si vas en velocidad, la respuesta de Andrey Yazu lo tiene. Estoy desgarrado en cuanto a lo que siento que es más legible. Siempre encuentro lambdas feas de alguna manera, pero en general, creo que sigue siendo el método más legible.

Edición 2: Con tuplas muy grandes:

Longitud 20:

 python -m timeit -s "x=tuple(list(range(1,10))*2)" "int(''.join(map(str, x)))" 100000 loops, best of 3: 5.45 usec per loop python -m timeit -s "x=tuple(list(range(1,10))*2)" "sum((10**pos)*val for pos, val in enumerate(reversed(x)))" 100000 loops, best of 3: 11.7 usec per loop python -m timeit -s "x=tuple(list(range(1,10))*2)" -s 'from functools import reduce' 'reduce(lambda rst, d: rst * 10 + d, x)' 100000 loops, best of 3: 4.18 usec per loop 

Longitud 100:

 python -m timeit -s "x=tuple(list(range(1,10))*10)" "int(''.join(map(str, x)))" 100000 loops, best of 3: 18.6 usec per loop python -m timeit -s "x=tuple(list(range(1,10))*10)" "sum((10**pos)*val for pos, val in enumerate(reversed(x)))" 10000 loops, best of 3: 72.9 usec per loop python -m timeit -s "x=tuple(list(range(1,10))*10)" -s 'from functools import reduce' 'reduce(lambda rst, d: rst * 10 + d, x)' 10000 loops, best of 3: 25.6 usec per loop 

Aquí vemos que el método más rápido es en realidad la operación de cadena; sin embargo, la realidad es que es poco probable que esté utilizando esto fuera del rango de, digamos, números de 10 dígitos, donde el método reduce() aún domina la velocidad. También diría que el método de la cadena es truculento y menos claro para el lector, que normalmente sería la prioridad sobre la velocidad.

esto no convierte los enteros en cadenas y los acumula:

 >>> sum([(10 ** i) * input[len(input)-i-1] for i in range(len(input))]) 123 

este es un for-loop en una línea.

La solución de bytearray @Marcin es, de hecho, la más rápida en Python 2.

Siguiendo la misma línea en Python 3 se podría hacer:

 >>> plus = ord("0").__add__ >>> int(bytes(map(plus, x))) 

Python 3 maneja la cadena y los bytes de una manera diferente a Python 2, así que para entender mejor la situación hice un poco de tiempo. Los siguientes son los resultados que obtuve en mi máquina.

Con Python 2.7 ( código ):

 int(str(bytearray(map(plus, x)))) 8.40 usec/pass int(bytearray(map(plus, x)).decode()) 9.85 usec/pass int(''.join(map(str, x))) 11.97 usec/pass reduce(lambda rst, d: rst * 10 + d, x) 22.34 usec/pass 

Mientras que con Python 3.2 ( código ):

 int(bytes(map(plus, x))) 7.10 usec/pass int(bytes(map(plus, x)).decode()) 7.80 usec/pass int(bytearray(map(plus,x)).decode()) 7.99 usec/pass int(''.join(map(str, x))) 17.46 usec/pass reduce(lambda rst, d: rst * 10 + d, x) 19.03 usec/pass 

Juzguen ustedes mismos 🙂

Qué tal si:

 In [19]: filter(set('0123456789').__contains__,str((1,2,3))) Out[19]: '123' 

Creo que esta es la solución más simple.

Una solución muy rápida es:

 plus=ord("0").__add__ # separate out for readability; bound functions are partially-applied functions int(str(bytearray(map(plus,x)))) #str is necessary 

Cómo eso se compara con la siguiente solución más rápida:

 $ python -m timeit -s 'x=tuple(list(range(1,10))*10)' 'plus=ord("0").__add__;int(str(bytearray(map(plus,x))))' 10000 loops, best of 3: 47.7 usec per loop $ python -m timeit -s "x=tuple(list(range(1,10))*10)" "int(''.join(map(str, x)))" 10000 loops, best of 3: 59 usec per loop 

El método más simple para cambiar una tupla en un número es usar el formato de cadena.

 input = (1, 3, 7) output = int('{}{}{}'.format(input[0], input[1], input[2])) # TEST print(output) # 137 print(type(output)) #  

Solo otra forma de hacerlo

 >>> sum(n*10**i for (i,n) in enumerate(input[::-1])) 137 

y otra mas

 >>> int(str(input).translate(None,'(,) ')) 137