Python通过模式分割字符串

6
我有像"aaaaabbbbbbbbbbbbbbccccccccccc"这样的字符串。 字符的数量可能会不同,有时字符串内部可能会带有破折号,例如"aaaaa-bbbbbbbbbbbbbbccccccccccc"
是否有一种聪明的方法可以将其拆分为"aaaaa""bbbbbbbbbbbbbb""ccccccccccc"并获取其被拆分的索引,或者只获取索引而无需循环遍历每个字符串?如果连字符位于两个模式之间,则它可能最终出现在左侧或右侧,只要始终以相同的方式处理即可。
有什么想法吗?
3个回答

11

正则表达式MatchObject的结果包括匹配的索引。现在需要匹配重复出现的字符:

正则表达式MatchObject的结果包括匹配的索引。现在需要匹配重复出现的字符:

import re

repeat = re.compile(r'(?P<start>[a-z])(?P=start)+-?')

只有当给定的字母字符 (a-z) 至少重复一次时才会匹配:

>>> for match in repeat.finditer("aaaaabbbbbbbbbbbbbbccccccccccc"):
...     print match.group(), match.start(), match.end()
... 
aaaaa 0 5
bbbbbbbbbbbbbb 5 19
ccccccccccc 19 30

.start().end()方法可以给出匹配结果在原字符串中的确切位置。

连字符包含在匹配结果中,但不包括不重复的字符:

>>> for match in repeat.finditer("a-bb-cccccccc"):
...     print match.group(), match.start(), match.end()
... 
bb- 2 5
cccccccc 5 13

如果您希望 a- 部分匹配,只需用 * 乘数替换 + 即可:

repeat = re.compile(r'(?P<start>[a-z])(?P=start)*-?')

我该如何保留破折号? 例如:"aaaaa-","bbbbbbbbbbbbbb","ccccccccccc"。 - Trollbrot
@Fritz:抱歉,我以为你不想要它们。重新阅读后,我发现你确实需要它们。我已经将它们与前面的信一起包含了。 - Martijn Pieters
太好了!非常感谢。我想我应该更深入地研究正则表达式。 - Trollbrot

3
使用 itertools.groupby 怎么样?
>>> s = 'aaaaabbbbbbbbbbbbbbccccccccccc'
>>> from itertools import groupby
>>> [''.join(v) for k,v in groupby(s)]
['aaaaa', 'bbbbbbbbbbbbbb', 'ccccccccccc']

这将把-作为它们自己的子字符串,很容易被过滤掉。
>>> s = 'aaaaa-bbbbbbbbbbbbbb-ccccccccccc'
>>> [''.join(v) for k,v in groupby(s) if k != '-']
['aaaaa', 'bbbbbbbbbbbbbb', 'ccccccccccc']

你能想到一个好的方法来获取索引吗?我能想到的最好的方法是 grouped = [(k, list(g)) for k,g in groupby(enumerate(s), key=lambda x: x[1])]; [(k, g[0][0], g[-1][0]) for k,g in grouped]。在Python 3中,我猜你也可以在长度上使用 accumulate - DSM
@DSM -- 对的,我忽略了索引的部分...不确定有没有好的方法来清晰地解决这个问题... - mgilson

0
str="aaaaabbbbbbbbbbbbbbccccccccccc"
p = [0] 
for i, c in enumerate(zip(str, str[1:])):
    if c[0] != c[1]:
        p.append(i + 1)
print p

# [0, 5, 19]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接