2013-04-18 15 views
6

Mam ciągi takie jak "aaaaabbbbbbbbbbbbbbccccccccccc". Liczba znaków może się różnić, a czasami w ciągu znaków może być myślnik, np. "aaaaa-bbbbbbbbbbbbbbccccccccccc".Python split string według wzorca

Czy jest jakiś sprytny sposób albo podzielić ją "aaaaa", "bbbbbbbbbbbbbb", "ccccccccccc" i uzyskać wskaźników były podzielone czy to jest po prostu indeksy, bez zapętlenie przez każdy ciąg? Jeśli myślnik znajduje się pomiędzy wzorami, może się kończyć w lewo lub w prawo, o ile zawsze jest traktowany tak samo.

Każdy pomysł?

Odpowiedz

11

Wyrażenie regularne MatchObject wyniki zawierają indeksy meczu. Pozostaje dopasować powtarzające się znaki:

import re 

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

będzie pasować tylko wtedy, gdy dana postać liter (a - z) powtarza się co najmniej raz:

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

The .start() i .end() metod na wynik meczu podać dokładne pozycje w ciągu wejściowym.

Kreski są zawarte w meczach, ale nie non-powtórzenie znaków:

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

Jeśli chcesz a- część być mecz, po prostu zastąpić + z * mnożnika:

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

Jak mogę zachować kreski? Na przykład "aaaa -", "bbbbbbbbbbbbbb", "cccccccccccc". – Trollbrot

+0

@Fritz: Przepraszam, myślałem, że ich nie chcesz. Po ponownym przeczytaniu, widzę, że robisz. Zawarłem je z poprzednimi literami. –

+0

Świetnie! Wielkie dzięki. Chyba powinienem zagłębić się w wyrażenia regularne. – Trollbrot

3

Co z użyciem itertools.groupby?

>>> s = 'aaaaabbbbbbbbbbbbbbccccccccccc' 
>>> from itertools import groupby 
>>> [''.join(v) for k,v in groupby(s)] 
['aaaaa', 'bbbbbbbbbbbbbb', 'ccccccccccc'] 

To będzie umieścić - jak własne podciągi, które mogą być łatwo odfiltrowane.

>>> s = 'aaaaa-bbbbbbbbbbbbbb-ccccccccccc' 
>>> [''.join(v) for k,v in groupby(s) if k != '-'] 
['aaaaa', 'bbbbbbbbbbbbbb', 'ccccccccccc'] 
+0

Czy możesz wymyślić ładny sposób na uzyskanie indeksów? Najlepszym, co potrafię wymyślić, to: 'grouped = [(k, list (g)) dla k, g w groupby (wyliczenie (s), klucz = lambda x: x [1])]; [(k, g [0] [0], g [-1] [0]) dla k, g w zgrupowaniu] '. W python 3 myślę, że można również użyć 'akumuluj' na długości. – DSM

+0

@ DSM - Right. Tęskniłem za częścią dotyczącą indeksów ... Nie jestem pewien, czy można to łatwo uzyskać ... – 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]