2016-06-21 49 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为非常整洁的解决方案。不幸的是不支持输入(以得到基于它的下一个值),但不应该难以添加。 –