将整数列表转换为一个数字?
我有一个整数列表,我想转换为一个数字,如:
numList = [1, 2, 3] num = magic(numList) print num, type(num) >>> 123, <type 'int'>
实现魔术function的最好方法是什么?
编辑
我确实发现了这一点 ,但好像还有更好的办法。
# 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)
两种解决scheme
>>> 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
以map
导向的解决scheme实际上是在我的盒子上出现的 – 你绝对不应该使用sum
可能是大数的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()
def magic(numbers): return int(''.join([ "%d"%x for x in numbers]))
def magic(number): return int(''.join(str(i) for i in number))
为了完整起见,下面是一个使用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)
不同解决scheme的时间performance
我测量了@ cdleary函数的性能。 结果稍有不同。
每个functiontesting与input列表生成的:
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)
numlen(nums)
在1..30def _accumulator(nums): tot = 0 for num in nums: tot *= 10 tot += num return tot
-
len(nums)
numlen(nums)
在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(列表号) { int tot = 0 while(!nums.isEmpty()) { int digit = nums.takeFirst() tot * = 10 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
使用生成器expression式:
def magic(numbers): digits = ''.join(str(n) for n in numbers) return int(digits)
如果列表只包含整数:
reduce(lambda x,y: x*10+y, list)
一个单线不需要投入和退出
def magic(num): return sum(e * 10**i for i, e in enumerate(num[::-1]))
我发现一些例子不兼容python 3我testing@Triptych一个
s = filter(str.isdigit, repr(numList))
num = int(s)
在python3它会给错误
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])