Is there any function that can convert a tuple into an integer?
Example:
input = (1, 3, 7)
output = 137
>>> reduce(lambda rst, d: rst * 10 + d, (1, 2, 3))
123
reduce() is functools.reduce().reduce() here is essentially a classical method for polynomial factorization, known as Horner's method.>>> x = (1,3,7)
>>> int(''.join(map(str,x)))
137
x = (1, 9, 10, 15). It's not clear if the OP wants to handle them too or not.(1, 9, 10, 15) to mean 191015 or 15*1+10*10+9*100+1*1000. Either could be considered valid depending on how you approach the problem. Is he considering the input a set of digits or a set of values split by base?(1, 9, 10, 15) as 15*1+10*10+9*100+1*1000.While converting it to a string then to an int works, it's a somewhat hackish method. We have all the information we need to make a number, namely:
As we have this information, we can calculate the number by calculating the value of each unit at each position, then multiplying it up by the digit at said position. We then add together the results and we have our number. This can be done in one line like so:
test = (1, 2, 3)
sum((10**pos)*val for pos, val in enumerate(reversed(test)))
Let's break this down:
>>> list(enumerate(reversed(test)))
[(0, 3), (1, 2), (2, 1)]
So then, if we multiply it up:
>>> list((10**pos)*val for pos, val in enumerate(reversed(test)))
[3, 20, 100]
So we just sum to get 123.
Edit: A note on speed:
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
So if you are going on speed, Andrey Yazu's answer has it. I'm torn as to what I feel is more readable. I always find lambdas ugly somehow, but in general, I think it's still the more readable method.
Edit 2: With very large tuples:
Length 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
Length 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
Here we see that the fastest method is actually the string operation - however, the reality is you are unlikely to be using this outside of the range of, say, 10 digit numbers - where the reduce() method still dominates speed-wise. I would also argue that the string method is hackish and less clear to the reader, which would normally be the priority over speed.
sum(10**i*x for i,x in enumerate(x[::-1])) but now I won't hahareversed() is a better option than [::-1] as it can be faster and is nicer to read.enumerate and reversed have such long names...@Marcin bytearray solution is indeed the fastest one in Python 2.
Following the same line in Python 3 one could do:
>>> plus = ord("0").__add__
>>> int(bytes(map(plus, x)))
Python 3 handles string and bytes in a different way than Python 2, so in order to understand better the situation I did a little timings. The following are the results I got on my machine.
With Python 2.7 (code):
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
While with Python 3.2 (code):
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
Judge by yourselves :)
How about:
In [19]: filter(set('0123456789').__contains__,str((1,2,3)))
Out[19]: '123'
I believe this is the simplest solution.
A very fast solution is:
plus=ord("0").__add__ # separate out for readability; bound functions are partially-applied functions
int(str(bytearray(map(plus,x)))) #str is necessary
How that stacks up against the next-fastest solution:
$ 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
__functions__ isn't a good idea, especially when there are other options available, right?str is never going to lose the __contains__ method, and this avoids both (python) function-call, and operator-resolution overheads.['1', '2', '3'], not '123', and the requested output either way was an int - not a string.__add__() a better option is to use functools.partial() and operator.add() and do plus = partial(add, ord("0")).Just another way to do it
>>> sum(n*10**i for (i,n) in enumerate(input[::-1]))
137
and yet another
>>> int(str(input).translate(None,'(,) '))
137
reverse(input) instead of input[::-1].
x = (1, 9, 10, 150)? If it is, could you specify what output should have? Please provide more information.