2016-06-21 75 views
0

我正在寫一個函數來遞增3個字母(a-z)的字符串。例如:
輸入: AAA
輸出:BAA在Python中遞增字符串

輸入: ZBA
輸出:ACA

所以順序如下

aaa 
baa 
... 
zaa 
aba 
bba 
cba 
... 
zba 
aca 
bca 
cca 
... 
zca 
ada 
... 
zzz 
aaa 

我寫了下面的f結next_code()和它的作品,但我想知道是否有實現它,而不是通過個別字母串在循環更優雅的方式:

# 0 = a; 25 = z 
def digit_to_char(digit): 
    return chr(ord('a') + digit) 

# a = 0; z = 25 
def char_to_digit(char): 
    return ord(char)-ord('a') 

def next_code(code): 
    # if used up all codes, loop from start 
    if code == 'zzz': 
     return next_code('aaa') 
    else: 
     code = list(code) 
     # loop over letters and see which one we can increment 
     for (i, letter) in enumerate(code): 
      if letter == 'z': 
       # go on to the next letter 
       code[i] = 'a' 
       continue 
      else: 
       # increment letter 
       code[i] = digit_to_char(char_to_digit(letter) + 1) 
       return ("".join(code)) 
       break 



print (next_code('aab')) 

回答

2

可以簡化環路很多:

def next_code(code): 
    code = list(code) 
    for i, let in enumerate(code): 
     if let != 'z': 
      code[i] = chr(ord(let) + 1) 
      break 
     code[i] = 'a' 
    return ''.join(code) 

如果目標是剛剛產生的所有值一個接一個,從'aaa'itertools.product可用於製作發電機:

from future_builtins import map # Only on Python 2 
from itertools import product 

def allcodes(): 
    # You want the left side to vary faster, so reverse before joining 
    return map(''.join, map(reversed, product(string.ascii_lowercase, repeat=3))) 

for code in allcodes(): 
    print(code) 

或者您可以根據需要調用該函數以獲取序列中的下一個代碼,而不必將其用作迭代器:

nextcode = allcodes().__next__ # .next on Py2 

如果發電機應爲無窮大(所以從zzz換到aaa),只是改變allcodes要麼:

# Avoid cycle if storing all 26**3 codes in memory is a bad idea 
def allcodes(): 
    while True: 
     yield from map(''.join, map(reversed, product(string.ascii_lowercase, repeat=3))) 
     # On Py2, change yield from line to: 
     # for code in map(''.join, map(reversed, product(string.ascii_lowercase, repeat=3))): yield code 

或更高的存儲成本,而且更簡單:

from itertools import cycle 

def allcodes(): 
    return cycle(map(''.join, map(reversed, product(string.ascii_lowercase, repeat=3)))) 
+0

很好的回答...你爲這個傢伙覆蓋瞭如此多的基地+1從我:) –

+0

@JoranBeasley:TIMTOWTDI? :-)我喜歡找到他們。我從Perl開始。 – ShadowRanger

+0

TSBO - APOO - OWTDI:P(lol) –

6

只使用itertools產品

>>> import itertools 
>>> from string import ascii_lowercase 
>>> strings = itertools.product(*[ascii_lowercase]*3) 
>>> "".join(next(strings,"No More Combos...")) 
'aaa' 
>>> "".join(next(strings,"No More Combos...")) 
'aab' 
>>> "".join(next(strings,"No More Combos...")) 
'aac' 
... 

是怎麼我可能會做

如果要循環回結束後,「AAA」你可以使用itertools.cycle

strings = itertools.cycle(itertools.product(*[ascii_lowercase]*3)) 
+0

謝謝, +1爲非常整潔的解決方案。不幸的是不支持輸入(以得到基於它的下一個值),但不應該難以添加。 –