2017-02-07 167 views
1

假定字符串s可能包含幾個相鄰的短劃線。爲了簡單起見,我們稱這些事件爲「重複動機」。例如,下面的字符串s包含破折號五個重複的動機,即長度3,2,6,5和1確定字符串中字符重複的長度和位置

​​

我想拿出一個返回各自的長度和Python代碼在每個重複動機的串內的相應位置。優先,代碼返回一個元組列表,每個元組都是格式(長度,位置)。

sought_function(s) 
# [(3,5), (2,13), (6,22), (5,34), (1,41)] 

關於如何啓動此代碼,您有什麼建議嗎?

回答

5

您可以使用groupby

s = "abcde---fghij--klmnopq------rstuvw-----xy-z" 
from itertools import groupby 
[(next(g)[0], sum(1 for _ in g) + 1) for k, g in groupby(enumerate(s), lambda x: x[1]) if k == "-"] 
# [(5, 3), (13, 2), (22, 6), (34, 5), (41, 1)] 

或者作爲@Willem評論,更換sumlen

[(next(g)[0], len(list(g)) + 1) for k, g in groupby(enumerate(s), lambda x: x[1]) if k == "-"] 
# [(5, 3), (13, 2), (22, 6), (34, 5), (41, 1)] 
+0

不能你使用'LEN(..)'在這裏,而不是'總和(...)'。 –

+0

@WillemVanOnsem是的,我認爲'len(...)'也可以。 – Psidom

+0

@Psidom哇!在決定發佈之前,我已經在這個問題上討論了一個小時。感謝你及時的答覆。 –

1

如果你想編寫自己的功能:只需遍歷字符並在內存中保存當前長度,如果序列被切斷,則產生該元素:

def find_sequences(s,to_find): 
    result = [] 
    lng = 0 
    for i,c in enumerate(s): 
     if c == to_find: 
      lng += 1 
     else: 
      if lng: 
       result.append((lng,i-lng)) 
      lng = 0 
    if lng: 
     result.append((lng,i-lng)) 
    return result 

so s是字符串,to_find是您感興趣的字符(這裏是'-')。

0

如果使用numpy的是罰款:

import numpy as np 
a = "abcde---fghij--klmnopq------rstuvw-----xy-z" 
bool_vec = np.array([letter == "-" for letter in a]) 
dots = np.where(np.diff(bool_vec)!=0)[0] + 1 
number = np.diff(dots.reshape((-1,2)),1).ravel() 
idx = dots[::2] 

number和包含你想要什麼:) idx兩個數組

+1

你可以進一步將這兩個列表拉到一起'zip(number,idx)' – wpercy

+0

是的,你完全正確;) –

0

你可以做re.split("(-+)", s)將返回[ 「ABCDE」 的列表,「 ---「,...],然後遍歷它。

0

這裏將是我這個建議:

import re 
s = "abcde---fghij--klmnopq------rstuvw-----xy-z" 
list1= [] 
for x in re.findall("[a-z]*-", s): 
    temp = x.strip("-") 
    if len(temp) > 0: 
     list1.append(temp) 
print(list1)