Python разделить строку по шаблону

у меня есть строки типа "aaaaabbbbbbbbbbbbbbccccccccccc". Количество символов может отличаться, и иногда внутри строки может быть тире, например "aaaaa-bbbbbbbbbbbbbbccccccccccc".

есть ли какой-либо умный способ либо разделить его "aaaaa","bbbbbbbbbbbbbb","ccccccccccc" и получить индексы были разделены или просто получить индексы, без цикла через каждую строку? Если тире находится между шаблонами, он может оказаться либо в левом, либо в правом, если он всегда обрабатывается одинаково.

есть идеи?

3 ответов


регулярные выражения 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)*-?')

как насчет использования 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']

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]