如何返回字母子串?

时间:2015-06-18 18:07:37

标签: python python-2.7 while-loop

我尝试编写一个函数,该函数将字符串s作为输入,并返回s中按字母顺序排列的子字符串列表。例如,s = 'acegibdh'应返回['acegi', 'bdh']

这是我提出的代码:

s = 'acegibdh'
ans = []
subs = []
i = 0
while i != len(s) - 1:
    while s[i] < s[i+1]:
        subs.append(s[i])
        i += 1
    if s[i] > s[i-1]:
        subs.append(s[i])
        i += 1
    subs = ''.join(subs)
    ans.append(subs)
    subs = []
print ans 

由于i + 1测试超出了索引范围,它一直遇到字符串的最后一个字母的问题。我花了很长时间来修补它,试图找到一种方法来避免这个问题。有谁知道怎么做?

7 个答案:

答案 0 :(得分:4)

为什么不将第一个字母硬编码到ans,然后只使用字符串的其余部分?您可以迭代字符串本身而不是使用索引。

>>> s = 'acegibdh'
>>> ans = []
>>> ans.append(s[0])
>>> for letter in s[1:]:
...     if letter >= ans[-1][-1]:
...             ans[-1] += letter
...     else:
...             ans.append(letter)
...
>>> ans
['acegi', 'bdh']

答案 1 :(得分:1)

s = 'acegibdh'
ans = []
subs = []
subs.append(s[0])
for x in range(len(s)-1):
    if s[x] <= s[x+1]:
        subs.append(s[x+1])
    if s[x] > s[x+1]:
        subs = ''.join(subs)
        ans.append(subs)
        subs = []
        subs.append(s[x+1])
subs = ''.join(subs)
ans.append(subs)
print ans 

如果您有任何问题,我决定稍微更改您的代码

答案 2 :(得分:1)

只是为了好玩,一线解决方案。

>>> s='acegibdh'
>>> [s[l:r] for l,r in (lambda seq:zip(seq,seq[1:]))([0]+[idx+1 for idx in range(len(s)-1) if s[idx]>s[idx+1]]+[len(s)])]
['acegi', 'bdh']

答案 3 :(得分:0)

不止一个while循环过度杀伤。我认为这更简单,满足您的要求。注意,这在空字符串上失败。

s = 'acegibdh'
ans = []
current = str(s[0])
i = 1
while i < len(s):
    if s[i] > s[i-1]:
        current += s[i]
    else: 
        ans.append(current)
        current = ''
    i += 1
if current != '':
   ans.append(current)
print ans 

答案 4 :(得分:0)

您应该尝试避免每次迭代多次增加位置的循环。

通常更清楚的是引入一个额外的变量来存储有关先前状态的信息:

s = 'acegibdh'
prev = None
ans = []
subs = []
for ch in s:
    if prev is None or ch > prev:
        subs.append(ch)
    else:
        ans.append(''.join(subs))
        subs = [ch]
    prev = ch
ans.append(''.join(subs))

我认为这更直接地读取(如果没有先前的字符,或者它仍然按字母顺序添加当前字符串,否则启动一个新的子字符串)。此外,您也无法通过此approch获得索引超出范围的问题。

答案 5 :(得分:0)

只是为了好玩,因为我喜欢做一些有点不同的事情

from itertools import groupby,chain,cycle

def my_gen(s):
    check = cycle([1,0])
    for k,v in groupby(zip(s,s[1:]),lambda x:x[0]<x[1]):
        if k:
            v = zip(*v)
            yield v[0] + (v[1][-1],)

print list(my_gen('acegibdhabcdefghijk'))

答案 6 :(得分:0)

发布的某些解决方案对空字符串有索引错误。

此外,您可以跟踪解决方案子字符串的起始索引i,而不是保留字符列表或重复字符串连接,并在s[i:j]处生成s[j] < s[j-1],然后将i设置为j

当下一个字母按字典顺序小于前一个字母时生成子字符串的生成器:

def alpha_subs(s):
    i, j = 0, 1
    while j < len(s):
        if s[j] < s[j-1]:
            yield s[i:j]
            i = j
        j += 1
    if s[i:j]:
        yield s[i:j]
print(list(alpha_subs('')))
print(list(alpha_subs('acegibdh')))
print(list(alpha_subs('acegibdha')))
[]
['acegi', 'bdh']
['acegi', 'bdh', 'a']

对于不区分大小写:

def alpha_subs(s, ignore_case=False):
    qs = s.lower() if ignore_case else s
    i, j = 0, 1
    while j < len(s):
        if qs[j] < qs[j-1]:
            yield s[i:j]
            i = j
        j += 1
    if s[i:j]:
        yield s[i:j]
print(list(alpha_subs('acEgibDh', True)))
print(list(alpha_subs('acEgibDh')))
['acEgi', 'bDh']
['ac', 'Egi', 'b', 'Dh']