跟踪字符串中字符迭代的列表
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
我正在编写一个编码器,我想保留一个列表来跟踪字符串中字符的迭代。
例如:
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