【问题标题】:Improve efficiency of modules提高模块效率
【发布时间】:2013-05-29 09:23:58
【问题描述】:

我在这种方法中运行循环大约 100 万次,但可能由于 O(n^2) 需要很多时间,所以有什么方法可以改进这两个模块:-

def genIndexList(length,ID):
   indexInfoList = []
   id = list(str(ID))
   for i in range(length):
       i3 = (str(decimalToBase3(i)))
       while len(i3) != 12:
           i3 = '0' + i3
       p = (int(str(ID)[0]) + int(i3[0]) + int(i3[2]) + int(i3[4]) + int(i3[6]) +     int(i3[8]) + int(i3[10]))%3
       indexInfoList.append(str(ID)+i3+str(p))
   return indexInfoList    

这是将数字转换为base3的方法:-

def decimalToBase3(num):
   i = 0
   if num != 0 and num != 1 and num != 2:
       number = ""
       while num != 0 :
           remainder = num % 3 
           num = num / 3 
           number = str(remainder) + number
       return int(number)
   else:
       return num

我正在使用python做一个软件,这两个功能是其中的一部分。请指出为什么这两个方法这么慢以及如何提高这些方法的效率。

【问题讨论】:

  • 我可以看到一些改进,是的,但是预期的输入和输出是什么?
  • 首先调用 getIndexList 方法,其中我提供一些巨大列表的长度作为参数,ID 是任何 2 位数字,我返回一个新列表,其项目附加有提供长度的原始列表。基本上一些细节被添加到原始列表中。
  • 为什么不传入列表本身?
  • 如果我通过了列表也没有用,那又如何呢?每次我需要将项目附加到我认为效率不高的列表时。
  • 关于循环的效率,您可以尝试直接增加以 3 为底的数组表示,而不是每次增加以 2 为底的表示并转换它们。好吧,事实上,为什么不直接增加 string 表示。

标签: algorithm python-2.7 big-o performance


【解决方案1】:

第一个函数可以简化为:

def genIndexList(length, ID):
   indexInfoList = []
   id0 = str(ID)[0]
   for i in xrange(length):
       i3 = format(decimalToBase3(i), '012d')
       p = sum(map(int, id0 + i3[::2])) % 3
       indexInfoList.append('{}{}{}'.format(ID, i3, p))
   return indexInfoList    

您可能希望将其改为生成器:

def genIndexList(length, ID):
   id0 = str(ID)[0]
   for i in xrange(length):
       i3 = format(decimalToBase3(i), '012d')
       p = sum(map(int, id0 + i3[::2])) % 3
       yield '{}{}{}'.format(ID, i3, p)

第二个功能可能是:

def decimalToBase3(num):
   if 0 <= num < 3: return num
   result = ""
   while num:
       num, digit = divmod(num, 3) 
       result = str(digit) + result
   return int(result)

下一步;您只是在生成一系列 base-3 数字。直接生成这些:

from itertools import product, imap
def base3sequence(l=12, digits='012'):
    return imap(''.join, product(digits, repeat=l))

这会产生 base3 值,0 填充到 12 位:

>>> gen = base3sequence()
>>> for i in range(10):
...     print next(gen)
... 
000000000000
000000000001
000000000002
000000000010
000000000011
000000000012
000000000020
000000000021
000000000022
000000000100

genIndexList() 变为:

from itertools import islice
def genIndexList(length, ID):
   id0 = str(ID)[0]
   for i3 in islice(base3sequence(), length):
       p = sum(map(int, id0 + i3[::2])) % 3
       yield '{}{}{}'.format(ID, i3, p)

【讨论】:

  • 那么这个第一个函数现在返回的是什么,它看起来不像一个列表.. 我不需要获取列表,我需要的只是数据作为一些数组,我可以从中取回它并且将其附加到相应索引的原始列表中
  • @hitman_93: original_list.extend(genIndexList(len(original_list), someid)) 会这样做。
  • 格式和映射是什么,它们给了我错误 p = sum(map(int, [id[0]] + i3[::2])) % 3 TypeError: can only concatenate要列出的列表(不是“str”)
  • @hitman_93:对不起,当然,i3 是一个字符串,而不是一个列表,所以我们可以在前面加上 id[0]
  • @hitman_93:如果您的代码超过 531440(最大的 12 位基 3 数字),则您的旧代码有问题,因为它开始生成更多 13 位或更多位。在这种情况下你想发生什么?我怀疑这将是一个错误,因为您开始忽略前 12 位以外的数字。
猜你喜欢
  • 2013-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 2015-10-08
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多