跟踪字符串中字符迭代的列表

List that keeps track of the iteration of characters in a string

我正在编写一个编码器,我想保留一个列表来跟踪字符串中字符的迭代。

例如:

Input = aaabccccaa
Output = [3, 1, 4, 2]

这是我的:

def numberCheck(string, numberList):
    teller = 1
    for i in range(len(string)):
        for j in range(i + 1,len(string)):
            if string[i] == string[j]:
                teller += 1
            else:
                break
        numberList.append(teller)
        teller = 1
    return numberList

但这给了我输出 [3, 2, 1, 1, 4, 3, 2, 1, 2, 1]

我知道为什么会出现这样的输出,但我不知道如何在代码中修复才能得到我想要的输出。

提前致谢

您的外循环在每个字符处启动内循环。您需要外循环才能前进到下一个不同字符块,而不是下一个。

要解决此问题,使用相同的算法,使用 while 循环,以便您可以调整循环控制变量的推进量 i:

def numberCheck(string):
    numberList = []
    teller = 1
    i = 0
    while i < len(string):
        for j in range(i + 1,len(string)):
            if string[i] == string[j]:
                teller += 1
            else:
                break
        numberList.append(teller)
        i += teller  # advance by the number of characters you just counted
        teller = 1
    return numberList

或者仅使用一个循环和一个条件(带有一些局部变量)来确定何时执行不同的操作。 (更新:请参阅 zondo 对此代码的回答)

(我是描述性的,而不是提供代码,因为这似乎是一个家庭作业问题)

无需为每个字母创建一个新循环,只需在外循环中将计数器重置为 1。另外,您不应该将数字列表传递给函数;它应该定义自己的:

def numberCheck(string):
    if not string:
        return []
    numberList = []
    current = string[0]
    i = 0 
    for char in string:
        if char == current:
            i += 1
        else:
            current = char
            numberList.append(i)
            i = 1 
    numberList.append(i)
    return numberList

您可以使用内置的 itertools for this task (specifically, groupby),而不是您拥有的长函数。

>>> from itertools import groupby
>>> Input = "aaabccccaa"
>>> [len(list(group)) for key, group in groupby(Input)]
[3, 1, 4, 2]

如果您想保留字母、它的计数及其在字符串中的出现顺序:

>>> [{k: len(list(group))} for key, group in groupby(Input)]
[{'a': 3}, {'b': 1}, {'c': 4}, {'a': 2}]

我认为 Andy 的 "right" 答案意味着它简洁易读。如果你关心时间,这大约快 25%。

from itertools import groupby

string = "aaabccccaa"
print [sum(1 for _ in group) for _, group in groupby(string)]
# [3, 1, 4, 2]

如果您真的关心时间,zondo 的解决方案比这快 50%。 10,000 次运行的近似基准:

me:    543 ms
andy:  746 ms
zondo: 286 ms

这是在 Python 2.7.

上完成的

编辑: 看起来 Andy 的版本在 Python 3.4 上更快:

me:    611
andy:  461
zondo: 254