How to convert a list of multiple integers into a single integer?
Solution 1
If you have a list of int
s and you want to join them together, you can use map
with str
to convert them to strings, join
them on the empty string and then cast back to int
s with int
.
In code, this looks like this:
r = int("".join(map(str, x)))
and r
now has the wanted value of 135
.
This, of course, is a limited approach that comes with some conditions. It requires the list in question to contain nothing else but positive int
s (as your sample) or strings representing int
s, else the steps of conversion to string might fail or the joining of (negative) numbers will be clunky.
Solution 2
Here is a more mathematical way that does not have to convert back and forth to string. Note that it will only work if 0 <= i <= 9.
>>> x = [1, 3, 5]
>>> sum(d * 10**i for i, d in enumerate(x[::-1]))
135
The idea is to multiply each element in the list by its corresponding power of 10 and then to sum the result.
Solution 3
Using only math (no conversions to or from strings), you can use the reduce
function (functools.reduce
in Python 3)
b = reduce(lambda total, d: 10*total + d, x, 0)
This makes use of Horner's rule, which factors the polynomial representing the number to reduce the number of multiplications. For example,
1357 = 1*10*10*10 + 3*10*10 + 5*10 + 7 # 6 multiplications
= ((1*10 + 3)*10 + 5)*10 + 7 # 3 multiplications
As a result, this is faster than computing powers of 10 or creating a string and converting the result to an integer.
>>> timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', 'from functools import reduce; x=[1,3,5,7]')
0.7217515400843695
>>> timeit.timeit('int("".join(map(str, [1,3,5,7])))')
1.425914661027491
>>> timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', 'x=[1,3,5,7]')
1.897974518011324
In fairness, string conversion is faster once the number of digits gets larger.
>>> import timeit
# 30 digits
>>> setup='from functools import reduce; x=[5, 2, 6, 8, 4, 6, 6, 4, 8, 0, 3, 1, 7, 6, 8, 2, 9, 9, 9, 5, 4, 5, 5, 4, 3, 6, 9, 2, 2, 1]'
>>> print(timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', setup))
6.520374411018565
>>> print(timeit.timeit('int("".join(map(str, x)))', setup))
6.797425839002244
>>> print(timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', setup))
19.430233853985555
# 60 digits
>>> setup='from functools import reduce; x=2*[5, 2, 6, 8, 4, 6, 6, 4, 8, 0, 3, 1, 7, 6, 8, 2, 9, 9, 9, 5, 4, 5, 5, 4, 3, 6, 9, 2, 2, 1]'
>>> print(timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', setup))
13.648188541992567
>>> print(timeit.timeit('int("".join(map(str, x)))', setup))
12.864593736943789
>>> print(timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', setup))
44.141602706047706
# 120 digits!
>>> setup='from functools import reduce; x=4*[5, 2, 6, 8, 4, 6, 6, 4, 8, 0, 3, 1, 7, 6, 8, 2, 9, 9, 9, 5, 4, 5, 5, 4, 3, 6, 9, 2, 2, 1]'
>>> print(timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', setup))
28.364255172084086
>>> print(timeit.timeit('int("".join(map(str, x)))', setup))
25.184791765059344
>>> print(timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', setup))
99.88558598596137
Solution 4
If you don't like map you can always use a list comprehension:
s = [str(i) for i in x]
r = int("".join(s))
homelessmathaddict
This user prefers to keep an air of mystery about them.
Updated on June 15, 2022Comments
-
homelessmathaddict almost 2 years
How do I convert a list in Python 3.5 such as:
x=[1, 3, 5]
to an integer (int) of
135
? -
brianpck over 7 years@LoïcFaure-Lacroix The OP specifically asks about an array of integers
-
chepner over 7 yearsThis is slower than computing the value numerically, but has the benefit of working for bases larger than 10.
-
Loïc Faure-Lacroix over 7 years@brianpck yes, I know but generic is sometimes better than not. Btw, the timeit tests are a good way to test things. What the answer doesn't say that the reduce method will get worse with big numbers. It's good with smaller numbers but as soon as it will get numbers with a length of around 30 numbers, the str version will be the fastest solution.
-
Loïc Faure-Lacroix over 7 years@chepner it will be faster with large numbers and your version is generally faster with smaller number (30 digit and less on my pc).
-
chepner over 7 years@LoïcFaure-Lacroix Good point, I tested the two numeric solutions with larger lists, but not the string conversion one. (I was curious about whether the overhead of user-defined functions would lose out, but I guess a linear number of function calls is still better than a quadratic number of multiplications.)
-
Loïc Faure-Lacroix over 7 yearsMy guess to explain why the mathematical method will get worse with large numbers is that adding large numbers is harder to do than converting a string to a large number once. The thing is that the string can technically convert the str to a large number directly. Not sure how they are stored in python, but I've seens a couple of BigNumber libararies storing large numbers as strings... But adding large number requires more arithmetic operation as numbers can't be stored completely in memory.
-
chepner over 7 yearsThe string method still has to do the work in converting a 30-character string to a 30-digit number, but the big difference is that it is done in C, not Python. Large-number libraries tend to work with large bases, for which strings provide a useful storage medium. (cf base-64 encoding)
-
Loïc Faure-Lacroix over 7 yearsYes, exactly. Your test seems not to be using
x
thought. -
chepner over 7 yearsFixed, and added some longer inputs to show
str
having a slight edge for very large numbers. -
Loïc Faure-Lacroix over 7 yearsThumbs up! That's a quite complete answer! Your solution is probably the best one with integers and "real" world number unless it's used for cryptography.
-
asmeurer over 7 yearsWorth noting that this version will fail if the first integer is 0.
-
Dimitris Fasarakis Hilliard over 7 years@asmeurer the solution isn't meant to address all possible inputs, just the one OP provided. I'm actually failing to see how a
0
in the beginning would make it fail though (theint
call will drop any leading zeros from the string while converting it). -
Kroltan over 7 years...and if you like list comprehensions you can always use a generator expression, and avoid one of the loops:
int("".join(str(i) for i in x))
-
Justin over 7 yearsIf you wanted it to be efficient, would've it be better to do
reversed(x)
rather thanx[::-1]
? The latter has to create an entirely new list, but the former just a generator. -
chepner over 7 years@asmeurer
int
doesn't try to infer the base from the string literal; it uses base 10 unless otherwise specified by the optional second argument. -
asmeurer over 7 yearsAh, my mistake. I assumed
int
would parse strings the same as the tokenizer, but apparently leading zeros are allowed. -
Yann Vernier almost 6 yearsThe factor
10
hardcodes thatd
is expected to be a single digit. Clarification on that point was requested in a question comment.