2012-10-26 117 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'數字'。