2017-02-07 30 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)