我有一个整数列表,想将它们转换为一个数,例如:
numList = [1, 2, 3]
num = magic(numList)
print num, type(num)
>>> 123, <type 'int'>
如何最好地实现magic函数?
编辑
我找到了这个,但似乎肯定有更好的方法。
# 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)
''.join(map(str, numList))
?另外,对于你的“聪明”的选项,你需要将结果转换为int类型。 - John Fouhyreduce(lambda n,d:10*n+d,..
比 'int(''.join(map(..` 更快。](https://gist.github.com/zed/ac0f5df365dffdb94f97476a89d38c8f#file-summary-org) - jfs有两种解决方案:
>>> 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
方式的解决方案确实更好 - 当你处理可能是大数字时,绝对不应该使用 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()
digit_count
,使用with_accumulator()更快。请参阅https://dev59.com/znRB5IYBdhLWcg3w26x3#493944。 - jfswith_accumulator
看起来更好。 - Andrei Suradef magic(number):
return int(''.join(str(i) for i in number))
[ ]
并将 str 作为生成表达式。int(''.join(str(i) for i in number))
- 这样会快两个字节! - dbr为了完整起见,这里有一个使用 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..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)))
|------------------------------+-------------------|
| 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
print(''.join(str(x) for x in [1,2,3,4,5]))
可以在Python 2.5、2.6、3.x等版本中使用,可能还有更多... - dbrdef magic(numbers):
return int(''.join([ "%d"%x for x in numbers]))
一行代码无需进行str
的转换
def magic(num):
return sum(e * 10**i for i, e in enumerate(num[::-1]))
int magic(list nums) { int tot = 0;
while (!nums.isEmpty()) { int digit = nums.takeFirst(); tot *= 10; tot += digit; }
return tot; }
如果列表只包含整数:
reduce(lambda x,y: x*10+y, list)
只要列表中的每个元素都只是一个数字,该方法在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)
int(''.join([str(n) for n in numList]))
- Ali Waqas