Python 中类似于 Ruby String#succ 的方法是什么?

4

我想知道在Python中是否有类似于Ruby的String#succ方法的函数(或方法),即:

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

1
没有现成的解决方案,你需要自己编写代码。 - Martijn Pieters
我一直很疑惑为什么'zzz'.succ会返回'aaaa'。这完全取决于地区设置。例如,在丹麦,它可能应该返回'ååå',因为å被视为一个单独的字母,排在z之后。 - Denis de Bernardy
@Denis 这是因为它是基于字符集而不是实际字母表实现的(当然这取决于所在地区)。 - mechanicalfish
1
使用这样的方法似乎不太符合Python的风格。也许你应该重新考虑一下? - agconti
1
@agconti 不太符合Python的风格?也许是,也许不是,但这并不是我用来构建应用程序的标准,你也不应该如此。我相信算法的使用,这是一个很好的起点,所以请随意批评我的算法。Pythonic...那只是营销手段,"Rubyist"也一样,在最后,性能、良好的算法和清晰的代码才是真正重要的。 - yeyo
显示剩余2条评论
1个回答

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('***')     - > **+ 

我还没有测试这段代码,但我可能会将您的代码推入我的应用程序中。非常感谢,Abhijit。还有一件事,为了让我能够接受您的答案,您能否编辑您的答案并明确说明Python内置库缺少此功能,这样我的问题就会得到完全回答。 - yeyo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接