2011-08-20 123 views
5

我試圖創建一個循環來生成並打印字符串如下:生成字母數字串順序

  1. 字母數字字符只有:
  2. 0-9 AZ之前,這是AZ之前,
  3. 長度最多可達4個字符。

所以,它會打印:

  1. 所有字符串從0-Z
  2. 然後從00-ZZ
  3. 然後從000-ZZZ
  4. 然後從0000-ZZZZ

然後停止。

+0

這太難理解你的問題了...... a07z會是一個合法的字符串嗎? – immortal

+0

是的。所有字母數字字符串長度1-4是合法的 – joseph

+0

所以當你說0-9在A-Z之前時,你的意思是0000應該在A000之前? – immortal

回答

17
from string import digits, ascii_uppercase, ascii_lowercase 
from itertools import product 

chars = digits + ascii_uppercase + ascii_lowercase 

for n in range(1, 4 + 1): 
    for comb in product(chars, repeat=n): 
     print ''.join(comb) 

這首先產生所有數字,大寫字母和小寫字母的字符串。

然後,從1-4的每個長度,它打印這些數字和字母的每個可能的組合。

請記住,這是結合了很多 - 62^4 + 62^3 + 62^2 + 62

+0

這是一個很酷的解決方案。另外一件很酷的事情就是讓它成爲一個發生器,而不是直接打印字符串。 – Drekembe

+0

我知道這是一大堆組合,我主要是爲了測試目的而做的。我把它縮小爲3個字符而不是4個 – joseph

+0

是的,他說他想要一個「打印字符串的循環」,這就是我給他的。 – agf

0

我不喜歡使用product我之前給出的答案,因爲在Python看着它的實現它似乎在開始產生結果之前將整個事物放入內存列表中。

這對你的情況非常糟糕,因爲正如agf自己所說的,這裏的排列數量很大(超過一百萬)。在這種情況下,創建yield聲明 - 這樣可以動態生成大量列表,而不是跨越內存(我也不喜歡浪費的range,其中xrange完全適用)。

我會去這樣一個解決方案:

def generate(chars, length, prefix = None): 
    if length < 1: 
     return 
    if not prefix: 
     prefix = '' 
    for char in chars: 
     permutation = prefix + char 
     if length == 1: 
      yield permutation 
     else: 
      for sub_permutation in generate(chars, length - 1, prefix = permutation): 
       yield sub_permutation 

這樣,所有在內存跨越是一個遞歸棧「N」深,其中「n」是你排列的長度(4在這種情況下),每次只返回一個元素。

chars是一組可供選擇的字符集,長度爲4,使用與產品非常相似,只是它在運行時不會跨越整個內存列表。

+2

它在產品描述中說 - 「除了實際的實現不會在內存中建立中間結果之外,這個函數與下面的代碼是等價的:」itertools中的所有工具都是這樣工作的,模塊的全部用途。 – agf

+0

此外,調用範圍(5)與xrange相比,浪費是一個有點拉伸... – hop

+0

我認爲,對於非常小的範圍,「範圍」實際上比'xrange'更浪費。 – agf

0

我今天就編碼了。它正是你想要的以及更多。它也可以擴展

def lastCase (lst): 
    for i in range(0, len(lst)): 
     if (lst[i] != '_'): 
      return False 
    return True 


l = [''] * 4 #change size here if needed. I used 4 
l[0] = '0' 
index = 0 

while (not lastCase(l)): 

    if (ord(l[index]) > ord('_')): 
     l[index] = '0' 
     index += 1 
     while(l[index] == '_'): 
      l[index] = '0' 
      index += 1 
     if (l[index] == ''): 
      l[index] = '0' 

    #print or process generated string 
    print(''.join(l)) 

    l[index] = chr(ord(l[index]) +1) 

    if (ord(l[index]) > ord('9') and ord(l[index]) < ord('A')): 
     l[index] = 'A' 
    elif (ord(l[index]) > ord('Z') and ord(l[index]) < ord('_') ): 
     l[index] = '_' 

    index = 0 

print (''.join(l))