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.
Another approach to convert a list of multiple integers into a single integer is to use map() function of Python with str function to convert the Integer list to string list. After this, join them on the empty string and then cast back to integer.
Use int() function to Convert list to int in Python. This method with a list comprehension returns one integer value that combines all elements of the list.
# 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)
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With