【问题标题】:Convert list of ints to one number?将整数列表转换为一个数字?
【发布时间】:2009-01-29 00:16:23
【问题描述】:

我有一个整数列表,我想将其转换为一个数字,例如:

numList = [1, 2, 3]
num = magic(numList)

print num, type(num)
>>> 123, <type 'int'>

实现magic功能的最佳方式是什么?

编辑
我确实找到了this,但似乎必须有更好的方法。

【问题讨论】:

  • 看来您假设基数为 10。是吗?

标签: python


【解决方案1】:
# 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 map、reduce、filter、lambda 本来都是 3k 的
  • 函数方法的小改进:reduce(lambda x,y: 10*x+y, numList)
【解决方案2】:

两种解决方案:

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

【讨论】:

  • 没问题,但请记住,您可能应该使用最易读的内容,除非您发现它是一个瓶颈。我只是喜欢计时。 ;-)
  • 我已经测量了上述功能的性能。结果略有不同,例如with_accumulator() 对于小的digit_count 更快。见stackoverflow.com/questions/489999/…
【解决方案3】:
def magic(number):
    return int(''.join(str(i) for i in number))

【讨论】:

  • Nitpick - 您可以删除 [ ] 并将字符串作为生成表达式。 int(''.join(str(i) for i in number)) - 快了两个字节!
【解决方案4】:
def magic(numbers):
    return int(''.join([ "%d"%x for x in numbers]))

【讨论】:

    【解决方案5】:

    为了完整起见,这里有一个使用 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's functions 的性能。结果略有不同。

    使用以下生成的输入列表测试的每个函数:

    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) 在 1..30

      def _accumulator(nums):
          tot = 0
          for num in nums:
              tot *= 10
              tot += num
          return tot
      
    • len(nums) 在 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 and 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:目的是使用打印功能。这是不推荐的方式,这就是我写“为了完整性”的原因。
    【解决方案6】:

    伪代码:

    int magic(list nums)
    {
      整数 = 0
    
      而 (!nums.isEmpty())
      {
        int 数字 = nums.takeFirst()
        总计 *= 10
        总数 += 数字
      }
    
      返回
    }

    【讨论】:

    • 我认为你错过了他正在寻找 python 解决方案的部分:P
    • 没关系 - Andrew 的解决方案实际上是转换为 Python 时最快的解决方案之一。来自我的 +1!
    • 如果列表大小小于 30,这是最快的解决方案(@cdleary 在 Python 中的实现)。stackoverflow.com/questions/489999/…
    【解决方案7】:

    只要列表中的每个元素只有一个数字,此方法就可以在 2.x 中使用。但是您实际上不应该使用它。太可怕了。

    >>> magic = lambda l:int(`l`[1::3])
    >>> magic([3,1,3,3,7])
    31337
    

    【讨论】:

      【解决方案8】:

      使用生成器表达式:

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

      【讨论】:

        【解决方案9】:

        无需在str 之间进行转换的单行代码

        def magic(num):
            return sum(e * 10**i for i, e in enumerate(num[::-1]))
        

        【讨论】:

          【解决方案10】:

          如果列表只包含整数:

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

          【讨论】:

          • 这对于不经意的观察者来说可能并不明显,所以警告:这仅适用于基数 10。如果列表中的项目大于 9,这似乎也不起作用。例如, [1, 250] 应该等于 1250,但答案是 260。这个答案按预期工作:stackoverflow.com/a/37451273/1030576
          【解决方案11】:

          对我来说,这看起来很干净。

          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。
          【解决方案12】:

          我发现一些示例与 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)))
          

          【讨论】:

            【解决方案13】:

            这可能会有所帮助

            def digits_to_number(digits):
                return reduce(lambda x,y : x+y, map(str,digits))
            
            print digits_to_number([1,2,3,4,5])
            

            【讨论】:

              【解决方案14】:

              如果你碰巧使用的是 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
              

              【讨论】:

                【解决方案15】:

                我在尝试根据 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 本身似乎无法在大端或小端系统上执行此操作。

                【讨论】:

                  【解决方案16】:

                  这里的聚会太晚了,没有转换成字符串的方法

                  x=0
                  k=len(a)-1
                  for i in a:
                      x+=(10**k)*i
                      k-=1
                  

                  【讨论】:

                    【解决方案17】:

                    我认为这似乎是最简单的解决方案不需要任何 fcn

                    res = int(''.join(numList))
                    

                    注意:此实现在 Python 3 中

                    【讨论】:

                    • 元素不是必须是字符串类型才能工作吗?
                    【解决方案18】:

                    希望这个单行公式也有用:

                    s=sum([numlist[i] * 10**(len(numlist)-i-1) for i in range(len(numlist))]) 
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2010-10-21
                      • 2012-12-04
                      • 2014-01-28
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-12-20
                      • 2015-07-24
                      相关资源
                      最近更新 更多