生成连续的字母数字

时间:2012-10-26 12:35:18

标签: python

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

E.g。 AAAAA00001, AAAAA00002, ......。 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)

有什么想法吗?

2 个答案:

答案 0 :(得分: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字符串所需的位数,但是您可以使用{{1 }}。例如

math.log10

请参阅我自己和@DSM关于数字部分的其他选项的评论 - 也可能存在优化机会。您需要fmtstring = '%s%0{size}d'.format(size=int(math.log10(rmax-1)+1)) 并查看。

答案 1 :(得分:1)

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

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's solution可能更快,因为使用itertools.product生成字母序列不要求您将序列号的上半部分分解为一组基数26'数字'。