如何在Python中按字母数字顺序获取下一个字符串?

5
我需要一个简单的程序,给定一个字符串,返回按字母数字顺序排列的下一个字符串(或仅按字母顺序排列)。
f("aaa")="aab"
f("aaZ")="aba"

等等。

已经有模块中的一个函数可以实现这个功能吗?


1
通常,库会公开函数是因为它们非常有用,而不是因为它们微不足道。如果确实有这个精确功能的库支持,我会感到惊讶,因为规范有点武断,我也想不出有任何一般用例需要这样的功能。 - Joe Holloway
好的,一般情况下需要一个字母表字符串和一个字母表列表作为输入,并返回其后继。你认为这与问题无关吗?实际上,有许多代数结构都是由后继函数和原始函数生成的,比如自然数。 - Pietro Speroni
我认为这些例子并不适用于按字母顺序给出下一个字符串的函数。按字母顺序,它应该返回f(aaa)=aaaa和f(aaZ)=aaZa。 - Jaakko Seppälä
4个回答

12

我认为没有内置函数可以实现这个功能。以下代码应该可以解决:

def next_string(s):
    strip_zs = s.rstrip('z')
    if strip_zs:
        return strip_zs[:-1] + chr(ord(strip_zs[-1]) + 1) + 'a' * (len(s) - len(strip_zs))
    else:
        return 'a' * (len(s) + 1)

解释:找到最后一个不是z的字符,将其加1,并用a替换其后的所有字符。如果整个字符串都是z,则返回长度比原字符串多1的全是a的字符串。


谢谢。运行得非常完美。(实际上,为了更准确,以防后来的人使用此代码,这只适用于小写字母。但对我来说没问题。祝好,Pietro) - Pietro Speroni
很遗憾,Python中没有本地方法来实现这个功能:http://www.ruby-doc.org/core-1.9.3/String.html#method-i-succ - Grocery

3

这个链接给出的答案是否足够?虽然不完全符合你的问题,但很接近...


2
一种不同的、更长但可能更易读和灵活的解决方案:
def toval(s):
    """Converts an 'azz' string into a number"""
    v = 0
    for c in s.lower():
        v = v * 26 + ord(c) - ord('a')
    return v

def tostr(v, minlen=0):
    """Converts a number into 'azz' string"""
    s = ''
    while v or len(s) < minlen:
        s = chr(ord('a') + v % 26) + s
        v /= 26
    return s

def next(s, minlen=0):
    return tostr(toval(s) + 1, minlen)

s = ""
for i in range(100):
    s = next(s, 5)
    print s

你可以将字符串转换成数字,每个字母代表26进制中的一位数字,将数字加1后再转换回字符串。这样,你就可以对以字母字符串表示的值进行任意数学运算。

"minlen"参数控制结果将有多少位数字(因为0 == a == aaaaa)。


1
很遗憾Python没有Ruby的String#next方法。所以这里提供一个糟糕的解决方案来处理字母数字字符串:
def next_string(s):
  a1 = range(65, 91)  # capital letters
  a2 = range(97, 123) # letters
  a3 = range(48, 58)  # numbers
  char = ord(s[-1])
  for a in [a1, a2, a3]:
    if char in a:
      if char + 1 in a:
        return s[:-1] + chr(char + 1)
      else:
        ns = next_string(s[:-1]) if s[:-1] else chr(a[0])
        return ns + chr(a[0])

print next_string('abc')  # abd
print next_string('123')  # 124
print next_string('ABC')  # ABD

# all together now
print next_string('a0')   # a1
print next_string('1a')   # 1b
print next_string('9A')   # 9B

# with carry-over
print next_string('9')    # 00
print next_string('z')    # aa
print next_string('Z')    # AA

# cascading carry-over
print next_string('a9')   # b0
print next_string('0z')   # 1a
print next_string('Z9')   # AA0

print next_string('199')  # 200
print next_string('azz')  # baa
print next_string('Zz9')  # AAa0

print next_string('$a')   # $b
print next_string('$_')   # None... fix it yourself

不太好。对我来说勉强能用。


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