2012-10-26 60 views
1

需要更好的方式来产生,通过ZZZZZ99999从AAAAA00001开始ascendingingly顺序串?顺序生成的字母数字编号

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) 

任何想法?

+0

你所说的“更好”是什么意思? – mgilson

+0

更好==在内存,可读性,可扩展性方面进行了优化等等等等 – infoadmin12345

+0

@Tichodroma - 这不是Base 36编码,但因为'AAAAA0000A'无效。 – mgilson

回答

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并查看。

+0

是的,我是那个人。 – iMom0

+0

@ iMom0 - 原来我也是:) – mgilson

+0

可以使用'product(string.digits,repeat = repeat)'来取代'%05d',而不是内部范围。 – DSM

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'数字'。