I have a list of integers that I would like to convert to one number like:
numList = [1, 2, 3] num = magic(numList) print num, type(num) >>> 123, <type 'int'>
What is the best way to implement the magic function?
EDIT
I did find this, but it seems like there has to be a better way.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
# Over-explaining a bit:
def magic(numList): # [1,2,3]
s = map(str, numList) # ['1','2','3']
s = ''.join(s) # '123'
s = int(s) # 123
return s
# How I'd probably write it:
def magic(numList):
s = ''.join(map(str, numList))
return int(s)
# As a one-liner
num = int(''.join(map(str,numList)))
# Functionally:
s = reduce(lambda x,y: x+str(y), numList, '')
num = int(s)
# Using some oft-forgotten built-ins:
s = filter(str.isdigit, repr(numList))
num = int(s)
Method 2
Two solutions:
>>> nums = [1, 2, 3]
>>> magic = lambda nums: int(''.join(str(i) for i in nums)) # Generator exp.
>>> magic(nums)
123
>>> magic = lambda nums: sum(digit * 10 ** (len(nums) - 1 - i) # Summation
... for i, digit in enumerate(nums))
>>> magic(nums)
123
The map-oriented solution actually comes out ahead on my box — you definitely should not use sum for things that might be large numbers:

import collections
import random
import timeit
import matplotlib.pyplot as pyplot
MICROSECONDS_PER_SECOND = 1E6
FUNS = []
def test_fun(fun):
FUNS.append(fun)
return fun
@test_fun
def with_map(nums):
return int(''.join(map(str, nums)))
@test_fun
def with_interpolation(nums):
return int(''.join('%d' % num for num in nums))
@test_fun
def with_genexp(nums):
return int(''.join(str(num) for num in nums))
@test_fun
def with_sum(nums):
return sum(digit * 10 ** (len(nums) - 1 - i)
for i, digit in enumerate(nums))
@test_fun
def with_reduce(nums):
return int(reduce(lambda x, y: x + str(y), nums, ''))
@test_fun
def with_builtins(nums):
return int(filter(str.isdigit, repr(nums)))
@test_fun
def with_accumulator(nums):
tot = 0
for num in nums:
tot *= 10
tot += num
return tot
def time_test(digit_count, test_count=10000):
"""
:return: Map from func name to (normalized) microseconds per pass.
"""
print 'Digit count:', digit_count
nums = [random.randrange(1, 10) for i in xrange(digit_count)]
stmt = 'to_int(%r)' % nums
result_by_method = {}
for fun in FUNS:
setup = 'from %s import %s as to_int' % (__name__, fun.func_name)
t = timeit.Timer(stmt, setup)
per_pass = t.timeit(number=test_count) / test_count
per_pass *= MICROSECONDS_PER_SECOND
print '%20s: %.2f usec/pass' % (fun.func_name, per_pass)
result_by_method[fun.func_name] = per_pass
return result_by_method
if __name__ == '__main__':
pass_times_by_method = collections.defaultdict(list)
assert_results = [fun([1, 2, 3]) for fun in FUNS]
assert all(result == 123 for result in assert_results)
digit_counts = range(1, 100, 2)
for digit_count in digit_counts:
for method, result in time_test(digit_count).iteritems():
pass_times_by_method[method].append(result)
for method, pass_times in pass_times_by_method.iteritems():
pyplot.plot(digit_counts, pass_times, label=method)
pyplot.legend(loc='upper left')
pyplot.xlabel('Number of Digits')
pyplot.ylabel('Microseconds')
pyplot.show()
Method 3
def magic(number):
return int(''.join(str(i) for i in number))
Method 4
def magic(numbers):
return int(''.join([ "%d"%x for x in numbers]))
Method 5
Just for completeness, here’s a variant that uses print() (works on Python 2.6-3.x):
from __future__ import print_function
try: from cStringIO import StringIO
except ImportError:
from io import StringIO
def to_int(nums, _s = StringIO()):
print(*nums, sep='', end='', file=_s)
s = _s.getvalue()
_s.truncate(0)
return int(s)
Time performance of different solutions
I’ve measured performance of @cdleary’s functions. The results are slightly different.
Each function tested with the input list generated by:
def randrange1_10(digit_count): # same as @cdleary
return [random.randrange(1, 10) for i in xrange(digit_count)]
You may supply your own function via --sequence-creator=yourmodule.yourfunction command-line argument (see below).
The fastest functions for a given number of integers in a list (len(nums) == digit_count) are:
-
len(nums)in 1..30def _accumulator(nums): tot = 0 for num in nums: tot *= 10 tot += num return tot -
len(nums)in 30..1000def _map(nums): return int(''.join(map(str, nums))) def _imap(nums): return int(''.join(imap(str, nums)))

|------------------------------+-------------------| | Fitting polynom | Function | |------------------------------+-------------------| | 1.00 log2(N) + 1.25e-015 | N | | 2.00 log2(N) + 5.31e-018 | N*N | | 1.19 log2(N) + 1.116 | N*log2(N) | | 1.37 log2(N) + 2.232 | N*log2(N)*log2(N) | |------------------------------+-------------------| | 1.21 log2(N) + 0.063 | _interpolation | | 1.24 log2(N) - 0.610 | _genexp | | 1.25 log2(N) - 0.968 | _imap | | 1.30 log2(N) - 1.917 | _map |

To plot the first figure download cdleary.py and make-figures.py and run (numpy and matplotlib must be installed to plot):
$ python cdleary.py
Or
$ python make-figures.py --sort-function=cdleary._map > --sort-function=cdleary._imap > --sort-function=cdleary._interpolation > --sort-function=cdleary._genexp --sort-function=cdleary._sum > --sort-function=cdleary._reduce --sort-function=cdleary._builtins > --sort-function=cdleary._accumulator > --sequence-creator=cdleary.randrange1_10 --maxn=1000
Method 6
pseudo-code:
int magic(list nums)
{
int tot = 0
while (!nums.isEmpty())
{
int digit = nums.takeFirst()
tot *= 10
tot += digit
}
return tot
}
Method 7
This method works in 2.x as long as each element in the list is only a single digit. But you shouldn’t actually use this. It’s horrible.
>>> magic = lambda l:int(`l`[1::3]) >>> magic([3,1,3,3,7]) 31337
Method 8
Using a generator expression:
def magic(numbers):
digits = ''.join(str(n) for n in numbers)
return int(digits)
Method 9
A one-liner without needing to cast to and from str
def magic(num):
return sum(e * 10**i for i, e in enumerate(num[::-1]))
Method 10
if the list contains only integer:
reduce(lambda x,y: x*10+y, list)
Method 11
This seems pretty clean, to me.
def magic( aList, base=10 ):
n= 0
for d in aList:
n = base*n + d
return n
Method 12
I found some examples are not compatible with python 3 I test one from @Triptych
s = filter(str.isdigit, repr(numList))
num = int(s)
in python 3 it’s gonna give error
TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter'
i think the more simple and compatible way would be
def magic(num_list):
return int("".join(map(str, num_list)))
Method 13
This may be helpful
def digits_to_number(digits):
return reduce(lambda x,y : x+y, map(str,digits))
print digits_to_number([1,2,3,4,5])
Method 14
If you happen to be using numpy (with import numpy as np):
In [24]: x Out[24]: array([1, 2, 3, 4, 5]) In [25]: np.dot(x, 10**np.arange(len(x)-1, -1, -1)) Out[25]: 12345
Method 15
I found this thread while trying to convert a list to the real value of the underlying int in terms of a C-style pointer, but none of the other answers appear to work for this case. I think the following solution works as intended and could be useful to others even though it doesn’t necessarily answer the original question.
def listToInt(x, reverseBytes=False):
if reverseBytes:
x = x[::-1]
return reduce(lambda x,y: x*256+y, x)
listToInt([1, 249]) == 505
listToInt([249, 1], True) == 505
The primary value of this is to emulate the behavior of casting a byte array to another data type, e.g. uint16, which Python can’t seem to do natively, on either a big or little endian system.
Method 16
Too late for the party here is the approch without converting to string
x=0
k=len(a)-1
for i in a:
x+=(10**k)*i
k-=1
Method 17
I think this seems to be the simplest solution with no need for any fcn
res = int(''.join(numList))
NOTE: This implementation is in Python 3
Method 18
Hope this one-line formula can be useful too:
s=sum([numlist[i] * 10**(len(numlist)-i-1) for i in range(len(numlist))])
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0