我有一个整数列表,我想将其转换为一个数字,例如:
numList = [1, 2, 3]
num = magic(numList)
print num, type(num)
>>> 123,
实现魔术功能的最佳方法是什么?
编辑
我确实找到了这个,但是似乎必须有一个更好的方法。
您似乎以10为底。是吗?
@ S.Lott,yepper :)以10为底
# 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)
我本以为不推荐使用map函数,而希望使用列表理解功能,但是现在我再也找不到关于此效果的注释了。谢谢您,我将把它重新添加到我的词汇表中。
我假设您的"#我可能如何编写:"中存在一个错误,应该为.join(map(str, numList))?另外,对于"巧妙"选项,您需要将结果进行int()。
是的,您在#2中缺少的地图。有一会儿,我以为你真的在做魔术!
哈哈谢谢-我正在编辑一堆而错过了
TokenMacGuy:这是您的意思吗? -artima.com/weblogs/viewpost.jsp?thread=98196映射,缩小,过滤,lambda最初全部在3k中使用
前两种方法+1,"功能性"方式似乎有点愚蠢,而filter / str.isdigit方式似乎很可怕。
功能方法的小改进:reduce(lambda x,y:10 * x + y,numList)
@DaveRadcliffe:对于小len(numList),reduce(lambda n,d:10*n+d,..甚至比int(.join(map(..
两种解决方案:
>>> 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()更快。见stackoverflow.com/questions/489999/
def magic(number):
return int(''.join(str(i) for i in number))
Nitpick-您可以删除[ ]并将字符串作为生成表达式。 int(.join(str(i) for i in number))-其..快两个字节!
def magic(numbers):
return int(''.join(["%d"%x for x in numbers]))
仅出于完整性考虑,以下是使用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)中给定数量的整数,最快的函数是:
1..30中的len(nums)
def _accumulator(nums):
tot = 0
for num in nums:
tot *= 10
tot += num
return tot
30..1000中的len(nums)
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
那是用Python 2.6 / 3.0编写它的一种奇怪的方法。print(.join(str(x) for x in [1,2,3,4,5]))将在Python 2.5、2.6、3.x中工作,也许还有更多...
@dbr:目的是使用打印功能。不推荐这种方式,这就是为什么我写"为了完整性"。
使用生成器表达式:
def magic(numbers):
digits = ''.join(str(n) for n in numbers)
return int(digits)
只要列表中的每个元素只有一位数字,此方法就可以在2.x版本中使用。但您实际上不应使用此功能。这太糟糕了。
>>> magic = lambda l:int(`l`[1::3])
>>> magic([3,1,3,3,7])
31337
对我来说,这似乎很干净。
def magic( aList, base=10 ):
n= 0
for d in aList:
n = base*n + d
return n
reduce(lambda x, y: base*x + y, aList, 0)甚至更干净;)
@Xion:"清洁工"?不对某些人。 reduce()粗心使用经常会产生其他问题。我强烈建议您发布自己的答案,因为您的答案与本答案有很大不同。
这似乎不起作用。 [1,249]作为16的基数应等于505(256 + 249),但此表达式的结果为265。
伪代码:
int magic(list nums)
{
int tot = 0
while (!nums.isEmpty())
{
int digit = nums.takeFirst()
tot *= 10
tot += digit
}
return tot
}
我认为您错过了他正在寻找python解决方案的部分:P
没关系-安德鲁斯解决方案实际上是转换为Python时最快的解决方案之一。向我+1!
如果列表大小小于30,则它是最快的解决方案(Python中的@cdlearys实现)。stackoverflow.com/questions/489999/
如果列表仅包含整数:
reduce(lambda x,y: x*10+y, list)
对于临时观察者来说,它可能不太明显,因此请注意:这仅适用于基数10。如果列表中的项目大于9,这也不起作用。例如,[1,250]应等于1250 ,但答案是260。此答案按预期工作:stackoverflow.com/a/37451273/1030576
无需转换为str的单线
def magic(num):
return sum(e * 10**i for i, e in enumerate(num[::-1]))
这可能会有所帮助
def digits_to_number(digits):
return reduce(lambda x,y : x+y, map(str,digits))
print digits_to_number([1,2,3,4,5])
我发现一些示例与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)))
在尝试将列表转换为基于C样式指针的基础int的实际值时,我发现了该线程,但是在这种情况下,其他答案似乎都不起作用。我认为以下解决方案可以按预期工作,并且即使不一定解决原始问题,也可能对其他人有用。
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似乎都无法原生完成。
如果您碰巧正在使用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
Python:将整数列表高效转换为数字
本文探讨了如何将Python中的整数列表转换为一个数字,提供了多种实现方法,包括使用`int()`、`join()`、`reduce()`、`map()`等函数的组合。还进行了性能测试,比较了不同方法在处理不同长度列表时的速度,并分享了最佳实践,强调在没有性能瓶颈的情况下,可读性优先。
5482

被折叠的 条评论
为什么被折叠?



