我正在编写一个编码器,我想保留一个列表来跟踪字符串中字符的迭代。
例如:
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]
我知道为什么这是输出,但我不知道如何修复代码,以便我有我想要的输出。
提前致谢
答案 0 :(得分:4)
您可以使用内置itertools
执行此任务(特别是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}]
答案 1 :(得分:2)
不要为每个字母创建一个新循环,只需在外循环中将计数器重置为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
答案 2 :(得分:1)
我认为安迪拥有"权利"回答意味着它简洁易读。如果你关心时间,这大约要快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
答案 3 :(得分:0)
你的外循环在每个角色处开始内循环。你需要你的外部循环向前移动到下一个不同角色的块,而不是下一个。
要解决此问题,请使用相同的算法,使用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对此代码的回答)
(我是描述性的而不是提供代码,因为这似乎是一个家庭作业问题)