【发布时间】:2010-04-18 22:00:59
【问题描述】:
计算字符串中某个字符最长连续重复的最简单方法是什么?例如,以下字符串中“b”的最长连续重复:
my_str = "abcdefgfaabbbffbbbbbbfgbb"
将是 6,因为其他连续重复更短(分别为 3 和 2。)如何在 Python 中做到这一点?
【问题讨论】:
计算字符串中某个字符最长连续重复的最简单方法是什么?例如,以下字符串中“b”的最长连续重复:
my_str = "abcdefgfaabbbffbbbbbbfgbb"
将是 6,因为其他连续重复更短(分别为 3 和 2。)如何在 Python 中做到这一点?
【问题讨论】:
一个正则表达式示例怎么样:
import re
my_str = "abcdefgfaabbbffbbbbbbfgbb"
len(max(re.compile("(b+b)*").findall(my_str))) #changed the regex from (b+b) to (b+b)*
# max([len(i) for i in re.compile("(b+b)").findall(my_str)]) also works
编辑,我的 vs. interjays
x=timeit.Timer(stmt='import itertools;my_str = "abcdefgfaabbbffbbbbbbfgbb";max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=="b")')
x.timeit()
22.759046077728271
x=timeit.Timer(stmt='import re;my_str = "abcdefgfaabbbffbbbbbbfgbb";len(max(re.compile("(b+b)").findall(my_str)))')
x.timeit()
8.4770550727844238
【讨论】:
这是一个单行:
max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=='b')
解释:
itertools.groupby 将返回由连续相同字符组成的组,以及该组中所有项目的迭代器。对于每个这样的迭代器,len(list(y)) 将给出组中的项目数。取其中的最大值(对于给定字符)将给出所需的结果。
【讨论】:
这是我的代码,效率不高,但似乎有效:
def LongCons(mystring):
dictionary = {}
CurrentCount = 0
latestchar = ''
for i in mystring:
if i == latestchar:
CurrentCount += 1
if dictionary.has_key(i):
if CurrentCount > dictionary[i]:
dictionary[i]=CurrentCount
else:
CurrentCount = 1
dictionary.update({i: CurrentCount})
latestchar = i
k = max(dictionary, key=dictionary.get)
print(k, dictionary[k])
return
【讨论】:
这是我非常无聊、低效、直接的计数方法(interjay 的要好得多)。注意,我在这个没有解释器的小文本字段中写了这个,所以我没有测试它,我可能犯了一个非常愚蠢的错误,校对没有发现。
my_str = "abcdefgfaabbbffbbbbbbfgbb"
last_char = ""
current_seq_len = 0
max_seq_len = 0
for c in mystr:
if c == last_char:
current_seq_len += 1
if current_seq_len > max_seq_len:
max_seq_len = current_seq_len
else:
current_seq_len = 1
last_char = c
print(max_seq_len)
【讨论】:
last_char;除此之外,+1 提供了真正最简单的方法:这是程序员需要较少概念/技能的方法。顺便说一句,这不是“效率低下”:任何解决方案都需要查看字符串上的所有字符以提供正确的结果,因此其成本至少为 O(n):您的方法的时间成本为 O(n),所以它的效率相当高。轻微的效率改进是在 else: 块上更新 max_seq_len,因此它每个序列更新一次,而不是每个字符更新一次。
last_char 的观点,Ignacio 刚刚修复了它;)
使用游程编码:
import numpy as NP
signal = NP.array([4,5,6,7,3,4,3,5,5,5,5,3,4,2,8,9,0,1,2,8,8,8,0,9,1,3])
px, = NP.where(NP.ediff1d(signal) != 0)
px = NP.r_[(0, px+1, [len(signal)])]
# collect the run-lengths for each unique item in the signal
rx = [ (m, n, signal[m]) for (m, n) in zip(px[:-1], px[1:]) if (n - m) > 1 ]
# get longest:
rx2 = [ (b-a, c) for (a, b, c) in rx ]
rx2.sort(reverse=True)
# returns: [(4, 5), (3, 8)], ie, '5' occurs 4 times consecutively, '8' occurs 3 times consecutively
【讨论】: