python的Ruby String#succ的对应物?

时间:2013-12-21 16:44:09

标签: python

我想知道python中是否有一个函数(或方法),如Ruby的String#succ方法那样递增字符串,即:

~ $ irb --simple-prompt
>> '2'.succ
=> "3"
>> '99'.succ
=> "100"
>> 'zzz'.succ
=> "aaaa"
>>

1 个答案:

答案 0 :(得分:1)

以下实现是我可以通过ruby的String#succ

实现得到的最接近的实现
def succ(s):
    if not isinstance(s, (str,string)):
        raise TypeError("succ works only with strings")
    if not s: return
    if max(map(ord, s)) > 127:
        raise TypeError("succ currently only supports ascii")

    #Three different character category honoured
    #  1. ascii lowercase alpha
    #  2. ascii uppercase alpha
    #  3. digits
    #  4. ascii nonalpha characters (the entire ascii set)
    lower = string.ascii_lowercase + 'a'
    upper = string.ascii_uppercase + 'A'
    digits = string.digits + '0'
    nonalpha = map(chr, range(0, 256)) + [chr(0)]
    def incr(ch):
        '''
        Generates the next character in sequence using the following rules
            1. Incrementing a digit always results in another digit
            2. Incrementing a letter results in another letter of the same case.
            3. Incrementing nonalphanumerics uses the underlying
               character set’s collating sequence.
        '''
        if ch.isdigit(): return digits[ord(ch) - ord("0") + 1]
        if ch.islower(): return lower[ord(ch) - ord('a') + 1]
        if ch.isupper(): return upper[ord(ch) - ord('A') + 1]
        return nonalpha[ord(ch) + 1]
    def last(ch):
        '''
        Returns the last character in its catagory
        '''
        if ch.isdigit(): return digits[-2]
        if ch.islower(): return lower[-2]
        if ch.isupper(): return upper[-2]
        return nonalpha[-2]
    def first(ch):
        '''
        Returns the last first in its catagory
        '''
        if ch.isdigit(): return digits[0]
        if ch.islower(): return lower[0]
        if ch.isupper(): return upper[0]
        return nonalpha[0]
    def islast(ch):
        '''
        Checks if next increment would generate a carry
        '''
        return ch == last(ch)
    s = list(s)[::-1]
    carry = True
    try:
        index = next(i for i, e in enumerate(s) if e.isalnum())
    except StopIteration:
        index = 0
    while carry:

        if index == len(s): #Add a character for Overflow
            s.append(first(s[index - 1]))
            break
        carry =  True if islast(s[index]) else False
        s[index] = incr(s[index])
        index += 1
    return ''.join(s[::-1])

使用示例

succ('2')       - > 3         
succ('99')      - > 000       
succ('zzz')     - > aaaa      
succ('')        - > None      
succ('abcd')    - > abce      
succ('THX1138') - > THX1139   
succ('<<koala>>') - > <<koalb>> 
succ('1999zzz') - > 2000aaa   
succ('ZZZ9999') - > AAAA0000  
succ('***')     - > **+