Преобразовать список целых чисел в одно число?
У меня есть список целых чисел, которые я хотел бы преобразовать в одно число, например:
numList = [1, 2, 3]
num = magic(numList)
print num, type(num)
>>> 123, <type 'int'>
каков наилучший способ реализации магия
15 ответов:
# 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)
два решения:
>>> 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
-ориентированное решение на самом деле выходит вперед на моем окне-вы определенно не должны использоватьsum
для вещей, которые могут быть большими числами: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()
просто для полноты, вот вариант, который использует
print()
(работает на 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)
время выполнения различных решений
я измерил производительность @ функции cdleary. Результаты немного отличаются.
каждая функция проверена с помощью входного списка, созданного:
def randrange1_10(digit_count): # same as @cdleary return [random.randrange(1, 10) for i in xrange(digit_count)]
вы можете поставить вашу собственную функцию через
--sequence-creator=yourmodule.yourfunction
аргумент командной строки (см. ниже).в самые быстрые функции для заданного числа целых чисел в списке (
len(nums) == digit_count
) являются:
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 |
чтобы построить первый рисунок скачать
cdleary.py
иmake-figures.py
и (numpy
иmatplotlib
должен быть установлен на сюжет):$ python cdleary.py
или
$ 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
псевдо-код:
int magic(list nums) { int tot = 0 while (!nums.isEmpty()) { int digit = nums.takeFirst() tot *= 10 tot += digit } return tot }
Это кажется довольно чистым, для меня.
def magic( aList, base=10 ): n= 0 for d in aList: n = base*n + d return n
этот метод работает в 2.x до тех пор, пока каждый элемент в списке является только одной цифрой. Но вы не должны на самом деле использовать это. Это ужасно.
>>> magic = lambda l:int(`l`[1::3]) >>> magic([3,1,3,3,7]) 31337
используя выражение генератора:
def magic(numbers): digits = ''.join(str(n) for n in numbers) return int(digits)
ОДН-вкладыш без бросать К и от
str
def magic(num): return sum(e * 10**i for i, e in enumerate(num[::-1]))
Я нашел некоторые примеры не совместимы с python 3 я тестирую один из @Triptych
s = filter(str.isdigit, repr(numList))
num = int(s)
в python 3 это даст ошибку
TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter'
Я думаю, что более простой и совместимый способ будет
def magic(num_list): return int("".join(map(str, num_list)))
Это может быть полезным
def digits_to_number(digits): return reduce(lambda x,y : x+y, map(str,digits)) print digits_to_number([1,2,3,4,5])
Если вы случайно используете numpy (с
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
Я нашел этот поток, пытаясь преобразовать список в реальное значение базового int с точки зрения указателя c-стиля, но ни один из других ответов, похоже, не работает для этого случая. Я думаю, что следующее решение работает по назначению и может быть полезно другим, даже если оно не обязательно отвечает на исходный вопрос.
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
основное значение этого-эмулировать поведение приведения массива байтов к другой тип данных, например uint16, который Python, похоже, не может делать изначально, либо в большой, либо в маленькой системе endian.