2013-04-18 10 views
6

Ich habe Strings wie "aaaaabbbbbbbbbbbbbbccccccccccc". Die Anzahl der Zeichen kann unterschiedlich sein und manchmal kann ein Bindestrich innerhalb der Zeichenfolge vorkommen, wie "aaaaa-bbbbbbbbbbbbbbccccccccccc".Python Split String nach Muster

Gibt es eine intelligente Art und Weise zu entweder geteilt "aaaaa", "bbbbbbbbbbbbbb", "ccccccccccc" und erhalten die Indizes wurden sie aufgeteilt wird oder nur die Indizes erhalten, ohne jede Zeichenfolge Looping? Wenn der Strich zwischen den Mustern ist, kann er entweder in der linken oder rechten Seite enden, solange er immer gleich gehandhabt wird.

Irgendeine Idee?

Antwort

11

Regulärer Ausdruck MatchObject Ergebnisse enthalten Indizes der Übereinstimmung. Was bleibt, ist ich wiederholende Zeichen passen:

import re 

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

würde nur überein, wenn ein bestimmtes Buchstaben-Zeichen (a - z) mindestens einmal wiederholt werden:

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

Die .start() und .end() Methoden auf dem Spielergebnis geben Sie die genauen Positionen in der Eingabezeichenfolge an.

Bindestriche in den Spielen enthalten sind, aber nicht nicht wiederholende Zeichen:

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

Wenn Sie den a- Teil wollen ein Spiel sein, ersetzen Sie einfach die + mit einer * Dimension:

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

Wie könnte ich die Bindestriche behalten? Also zum Beispiel "aaaaa -", "bbbbbbbbbbbbbb", "ccccccccccc". – Trollbrot

+0

@Fritz: Entschuldigung, ich dachte du wolltest sie nicht. Beim nochmaligen Lesen sehe ich, dass du es tust. Ich habe sie mit den vorhergehenden Buchstaben eingefügt. –

+0

Großartig! Danke vielmals. Ich denke, ich sollte mir die regulären Ausdrücke genauer ansehen. – Trollbrot

3

Wie wäre es mit itertools.groupby?

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

Dies wird die - als ihren eigenen Teil setzen, die aus leicht gefiltert werden.

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

Können Sie sich einen schönen Weg vorstellen, die Indizes zu bekommen? Das Beste, was ich mir ohne weiteres vorstellen kann, ist gruppiert = [(k, Liste (g)) für k, g in groupby (Aufzählung (en), Schlüssel = Lambda x: x [1])]; [(k, g [0] [0], g [-1] [0]) für k, g gruppiert] '. In Python 3 könnte man auch 'accumulate' auf den Längen verwenden. – DSM

+0

@DSM - Rechts. Ich habe den Teil über Indizes verpasst ... Ich bin mir nicht sicher, ob es gut wäre, das sauber zu bekommen ... – 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]