2017-06-09 152 views
1

我有一個字符串:縮短字符串

a = babababbaaaaababbbab 

,它需要被縮短,所以它看起來是這樣的:

(ba)3(b)2(a)5ba(b)3ab 

所以基本上它需要採取所有重複的字符,寫多少他們重複而不是打印它們的次數。 我成功地做到一半這樣的:

from itertools import groupby 
a = 'babababbaaaaababbbab' 
grouped = ["".join(grp) for patt,grp in groupby(a)] 
solved = [str(len(i)) + i[0] for i in grouped if len(i) >= 2] 

但這只是做到這一點對於那些重複的,但不是模式字符。我知道我可以通過在字符串中查找'ab'模式來做到這一點,但這需要對每一個可能的字符串都是可行的。有沒有人遇到類似的東西?

+2

這可能是相關的:https://stackoverflow.com/questions/11090289/find-longest-repetitive-sequence-in-a-string –

+12

這是不明確的。 'aaabbbaaabbb'的預期輸出是什麼? (a)3(b)3(a)3(b)3'還是'(aaabbb)2'? –

+0

@SvenMarnach它是(3)b(3)。 – Nenad

回答

9

您可以輕鬆地regex做到這一點:

>>> repl= lambda match:'({}){}'.format(match.group(1), len(match.group())//len(match.group(1))) 
>>> re.sub(r'(.+?)\1+', repl, 'babababbaaaaababbbab') 
'(ba)3(b)2(a)5ba(b)3ab' 

這裏就不多解釋了。 (.+?)\1+模式匹配重複的字符序列,lambda函數將其重寫爲(sequence)number

+0

太棒了!我想我可以騰出一點時間來掌握正則表達式。真的很好的答案。 –

+0

對於'aabaabaab',這給出了一個相當不直觀的'(a)2(baa)2b',而不是'(aab)3'。雖然這並不是說這是錯的 - 問題有點不明確。 – Dukeling

+0

@Dukeling這符合OP關於'aaabbbaaabbb'變成'(a)3(b)3(a)3(b)3'的陳述 - 它重複儘可能短的序列。如果這是不可取的,你可以嘗試改變'(。+?)\ 1 +'到'(。+)\ 1 +',儘管它也有一些奇怪的怪癖 - 例如它會將'abababab'變成' )2'。 –

-2

我不確定你到底在找什麼,但希望這有助於你。

A=a.count('a') 
B=a.count('b') 
AB=a.count('ab') 
BAB=a.count('bab') 
BA=a.count('ba') 
print(A,'(a)',B,'(b)',AB,'(ab)',BAB,'(bab)',BA,'(ba)') 
+0

這似乎甚至沒有給出問題中的示例的正確輸出,不用管更普遍的問題。 – Dukeling

0

這是我想出了,代碼是一個爛攤子,但我只是想有一個快速的樂趣,所以我讓它成爲這樣

a = 'babababbaaaaababbbab' 

def compress(text): 
    for i in range(1, len(text) // 2): 
     for j, c in enumerate(text[:-i if i > 0 else len(text)]): 
      pattern = text[j:i+j] 
      new_text = pattern_repeats_processor(pattern, text, j) 
      if new_text != text: 
       return compress(new_text) 
    return text 

def pattern_repeats_processor(pattern, text, i): 
    chunk = pattern 
    count = 1 
    while chunk == pattern and i + (count + 1) * len(pattern) < len(text): 
     chunk = text[i + count * len(pattern): i + (count + 1) * len(pattern)] 
     if chunk == pattern: 
      count = count + 1 
     else: 
      break 
    if count > 1: 
     return text[:i] + '(' + pattern + ')' + str(count) + text[i + (count + 0) * len(pattern):] 
    return text 

print(compress(a)) 
print(a) 

它使 babababbaaaaababbbab = (ba)3(b)2(a)5ba(b)3ab

PS當然,賽艇的答案是英里更好,相當令人印象深刻即使