1

需要更好的方法来生成从 AAAAA00001 到 ZZZZZ99999 开始的升序字符串?

例如 AAAA00001、AAAA00002、……。AAAAA99999,AAAAB00001,…… ZZZZZ99999

当前正在使用的样本高度未优化(我觉得)如下:

def generateAlphanumericSequence():
    for i in range(65, 91):
        for j in range(65, 91):
            for k in range(65, 91):
                for l in range(65, 91):
                    for m in range(65, 91):
                        for z in range(1, 100000):
                            print '%s%s%s%s%s%05d' % (chr(i), chr(j), chr(k), chr(l), chr(m), z)

有任何想法吗?

4

2 回答 2

4

使用itertools.product.

from string import ascii_uppercase
import itertools
def generateAlphanumericSequence():
    for i,j,k,l,m in itertools.product(ascii_uppercase,repeat=5):
         for z in range(1, 100000):
              yield '%s%s%s%s%s%05d' % (i, j, k, l, m, z)

您可以轻松地将其概括为接受前面的任意数量的字符(如果您用于str.join修复 的输出itertools.product):

from string import ascii_uppercase
import itertools
def generateAlphanumericSequence(repeat=5):
    for seq in itertools.product(ascii_uppercase,repeat=repeat):
         sseq = ''.join(seq)
         for z in range(1, 100000):
              yield '%s%05d' % (sseq, z)

当然,您也可以使用范围的默认参数——您只需要弄清楚创建%0?d字符串需要多少位数,但您可以使用math.log10. 例如

fmtstring = '%s%0{size}d'.format(size=int(math.log10(rmax-1)+1))

有关数字部分的其他选项,请参阅我自己和@DSM 的评论——那里也可能有优化机会。你需要timeit看看。

于 2012-10-26T12:43:26.447 回答
1

您基本上是从 0 计数到 1188137599999 ((26 ** 5) * 100000 - 1),但超过 100000 的值以 26 为基数表示,只有字母。如果将数字格式与计数分开,您将得到:

from string import ascii_uppercase

def _format(value, lettercount=5, digitcount=5):
    upper, lower = divmod(value, 10 ** digitcount)
    letters = []
    for i in xrange(lettercount):
        upper, val = divmod(upper, 26)
        letters.insert(0, ascii_uppercase[val])
    return '%s%0*i' % (''.join(letters), digitcount, lower)

def lettercounter(lettercount=5, digitcount=5):
   for i in xrange((26 ** lettercount) * (10 ** digitcount)):
       yield _format(i, lettercount, digitcount)

它将有效地一一生成您的所有值。

演示:

>>> lettercounter().next()
'AAAAA00000'
>>> _format(123456789)
'AABVM56789'
>>> _format(26**5*100000-1)
'ZZZZZ99999'

这些函数还接受任意数字和字母长度:

>>> lettercounter(2, 2).next()
'AA00'

我的方法的优点是您可以将任意数字格式化为字母 + 数字序列号,以及生成从 0 开始的序列。但mgilson 的解决方案可能更快,因为itertools.product用于生成字母序列不需要您分解将序列号的上半部分转换为一组以 26 为基数的“数字”。

于 2012-10-26T12:53:39.130 回答