2010-04-18 71 views
9

計算字符串中某個字符的最長連續重複次數的最簡單方法是什麼?例如,在下面的字符串「B」的最長連續重複:計算Python中重複序列的最長出現次數

my_str = "abcdefgfaabbbffbbbbbbfgbb" 

將是6,因爲其他連續重複較短我怎樣才能在Python做到這一點(分別爲3和2。)?

回答

9

如何正則表達式的例子:

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 

編輯,礦山與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 
+0

+1幫助恢復部分恢復本網站正則表達式的價值 - 非常勇敢。 – doug 2010-04-19 04:29:35

4

這是我非常無聊,低效,直接的計數方法(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) 
+1

您可能需要更新循環中某處的'last_char';除此之外,+1提供真正的*最簡單*的方式:這是程序員較少的概念/技能要求的方法。順便說一句,它不是「無效率」:任何解決方案都需要查看字符串上的所有字符以提供正確的結果,因此它的成本至少爲O(n):您的方法的時間成本爲O(n),所以它效率很高。稍微提高效率就是更新'else:'塊的'max_seq_len',所以每個序列更新一次,而不是每個字符一次。 – 2010-04-18 22:16:21

+0

好吧,忽略我關於更新'last_char'的意見,Ignacio只是修正了它;) – 2010-04-18 22:18:50

+0

Thanks Ignacio;)(我只是意味着你不得不在多少打字方面效率低下) – 2010-04-18 22:35:54

9

這裏是一個班輪:

max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=='b') 

說明:

itertools.groupby將返回的連續的相同字符組,該組中的所有項的迭代器沿。對於每個這樣的迭代器,len(list(y))將給出組中的項目數量。取最大值(對於給定的字符)將得到所需的結果。

2

使用運行長度編碼:

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 
+0

如果(n - m)> 1「是」如果(n - m)> = 1「檢測到長度爲1的運行,不應該」 – 2012-08-10 03:43:58

+1

@carlo_hamalainen - no。對檢測1的「遊程長度」沒有真正的興趣。 – doug 2012-08-10 05:27:42

0

這裏是我的代碼,效率不高,但似乎工作:

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