[python] Convert list of ints to one number?

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.

This question is related to python

The answer is


# 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:

Timeit Comparison

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()

pseudo-code:

int magic(list nums)
{
  int tot = 0

  while (!nums.isEmpty())
  {
    int digit = nums.takeFirst()
    tot *= 10
    tot += digit
  }

  return tot
}

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]))

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:

Timeit Comparison

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()

def magic(numbers):
    return int(''.join([ "%d"%x for x in numbers]))

if the list contains only integer:

reduce(lambda x,y: x*10+y, list)

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

This seems pretty clean, to me.

def magic( aList, base=10 ):
    n= 0
    for d in aList:
        n = base*n + d
    return n

Using a generator expression:

def magic(numbers):
    digits = ''.join(str(n) for n in numbers)
    return int(digits)

Using a generator expression:

def magic(numbers):
    digits = ''.join(str(n) for n in numbers)
    return int(digits)

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

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..30

    def _accumulator(nums):
        tot = 0
        for num in nums:
            tot *= 10
            tot += num
        return tot
    
  • len(nums) in 30..1000

    def _map(nums):
        return int(''.join(map(str, nums)))
    
    def _imap(nums):
        return int(''.join(imap(str, nums)))
    

Figure: N = 1000

|------------------------------+-------------------|
| 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              |

Figure: N = 1000_000

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 

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:

Timeit Comparison

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()

pseudo-code:

int magic(list nums)
{
  int tot = 0

  while (!nums.isEmpty())
  {
    int digit = nums.takeFirst()
    tot *= 10
    tot += digit
  }

  return tot
}

This seems pretty clean, to me.

def magic( aList, base=10 ):
    n= 0
    for d in aList:
        n = base*n + d
    return n

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:

Timeit Comparison

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()

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]))

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.


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

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..30

    def _accumulator(nums):
        tot = 0
        for num in nums:
            tot *= 10
            tot += num
        return tot
    
  • len(nums) in 30..1000

    def _map(nums):
        return int(''.join(map(str, nums)))
    
    def _imap(nums):
        return int(''.join(imap(str, nums)))
    

Figure: N = 1000

|------------------------------+-------------------|
| 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              |

Figure: N = 1000_000

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 

def magic(number):
    return int(''.join(str(i) for i in number))

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..30

    def _accumulator(nums):
        tot = 0
        for num in nums:
            tot *= 10
            tot += num
        return tot
    
  • len(nums) in 30..1000

    def _map(nums):
        return int(''.join(map(str, nums)))
    
    def _imap(nums):
        return int(''.join(imap(str, nums)))
    

Figure: N = 1000

|------------------------------+-------------------|
| 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              |

Figure: N = 1000_000

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 

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

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

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.


def magic(numbers):
    return int(''.join([ "%d"%x for x in numbers]))

This seems pretty clean, to me.

def magic( aList, base=10 ):
    n= 0
    for d in aList:
        n = base*n + d
    return n

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

def magic(number):
    return int(''.join(str(i) for i in number))

def magic(numbers):
    return int(''.join([ "%d"%x for x in numbers]))

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])

Using a generator expression:

def magic(numbers):
    digits = ''.join(str(n) for n in numbers)
    return int(digits)

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])

def magic(number):
    return int(''.join(str(i) for i in number))

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

This seems pretty clean, to me.

def magic( aList, base=10 ):
    n= 0
    for d in aList:
        n = base*n + d
    return n

def magic(numbers):
    return int(''.join([ "%d"%x for x in numbers]))

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)))

Using a generator expression:

def magic(numbers):
    digits = ''.join(str(n) for n in numbers)
    return int(digits)

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)))

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

pseudo-code:

int magic(list nums)
{
  int tot = 0

  while (!nums.isEmpty())
  {
    int digit = nums.takeFirst()
    tot *= 10
    tot += digit
  }

  return tot
}

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..30

    def _accumulator(nums):
        tot = 0
        for num in nums:
            tot *= 10
            tot += num
        return tot
    
  • len(nums) in 30..1000

    def _map(nums):
        return int(''.join(map(str, nums)))
    
    def _imap(nums):
        return int(''.join(imap(str, nums)))
    

Figure: N = 1000

|------------------------------+-------------------|
| 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              |

Figure: N = 1000_000

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 

if the list contains only integer:

reduce(lambda x,y: x*10+y, list)

pseudo-code:

int magic(list nums)
{
  int tot = 0

  while (!nums.isEmpty())
  {
    int digit = nums.takeFirst()
    tot *= 10
    tot += digit
  }

  return tot
}