2009-09-03 4 views
22

Gibt es eine Möglichkeit, wie ich herausfinden kann, wie viele Übereinstimmungen einer Regex in einer Zeichenfolge in Python sind? Zum Beispiel, wenn ich die Zeichenfolge habe "It actually happened when it acted out of turn."Finden Sie heraus, wie oft eine Regex in einer Zeichenfolge in Python übereinstimmt

Ich möchte wissen, wie oft "t a" in der Zeichenfolge erscheint. In dieser Zeichenfolge erscheint "t a" zweimal. Ich möchte, dass meine Funktion mir sagt, dass es zweimal erschienen ist. Ist das möglich?

+0

Müssen Sie überlappende Übereinstimmungen zählen? Ist der Regex "Freund eines Freundes" ein- oder zweimal in der Zeichenfolge "Freund eines Freundes eines Freundes"? –

+0

Ich brauche Überlappung. – Dan

+2

Sie brauchen eine Überlappung? Wenn also das Übereinstimmungsmuster "aa" lautet und die Quellzeichenfolge "aaaa" lautet, lautet die richtige Antwort 3? – steveha

Antwort

16

Die bestehenden Lösungen auf Basis von findall sind in Ordnung für nicht überlappende Streichhölzer (und ohne Zweifel optimal außer vielleicht für große Anzahl von Spielen) zurückkehren, obwohl Alternativen wie sum(1 for m in re.finditer(thepattern, thestring)) (um zu vermeiden, jemals die Liste materialisieren, wenn alles, was Sie interessieren, ist die Zählung) sind auch durchaus möglich. Etwas eigenwillig subn und ignorieren würde den resultierenden String mit ...:

def countnonoverlappingrematches(pattern, thestring): 
    return re.subn(pattern, '', thestring)[1] 

die einzige wirkliche Vorteil dieser letztere Idee kommen würde, wenn Sie (sagen wir) bis zu 100 Spiele zählen betreut; dann könnte re.subn(pattern, '', thestring, 100)[1] praktisch sein (100 zurückgeben, ob es 100 Übereinstimmungen gibt, oder 1000 oder sogar größere Zahlen).

Zählen Überschneidungen Übereinstimmungen müssen Sie mehr Code schreiben, weil die integrierten Funktionen in Frage alle auf nicht überlappende Übereinstimmungen konzentriert sind. Es gibt auch ein Problem der Definition, z. B. mit Muster sein 'a+' und Thesestring 'aa', würden Sie dies als nur ein Spiel, oder drei (die erste a, die zweite, beide von ihnen), oder ...?

zum Beispiel Angenommen, die Sie wollen möglicherweise überlappende Streichhölzer in der Zeichenfolge an bestimmten Stellen beginnen (die dann zwei Spiele für das Beispiel im vorherigen Absatz ergeben würden):

def countoverlappingdistinct(pattern, thestring): 
    total = 0 
    start = 0 
    there = re.compile(pattern) 
    while True: 
    mo = there.search(thestring, start) 
    if mo is None: return total 
    total += 1 
    start = 1 + mo.start() 

Beachten Sie, dass Sie tun müssen das Muster in einem RE-Objekt in diesem Fall kompilieren: Funktion re.search akzeptiert kein start Argument (Startposition für die Suche) die Art und Weise Methode tut, also müssten Sie Strings schnitzen wie Sie gehen - definitiv mehr Aufwand als nur die nächste Suche s tart beim nächstmöglichen Startpunkt, was ich in dieser Funktion mache.

6

Haben Sie das versucht?

len(pattern.findall(source)) 
+1

es ist findall obwohl – cobbal

+0

Danke für die Korrektur! –

+0

Zählt das Überlappung? Er sagte, dass es das unterstützen muss. (Scheint als wäre das wirklich schwierig durchzuführen) –

30
import re 
len(re.findall(pattern, string_to_search)) 
+0

Toller Job !!! Danke –

0
import re 
print len(re.findall(r'ab',u'ababababa')) 
9

Ich weiß, dass dies eine Frage zu regex ist. Ich dachte nur, ich würde die count Methode für zukünftige Referenz erwähnen, wenn jemand eine Nicht-Regex-Lösung will.

>>> s = "It actually happened when it acted out of turn." 
>>> s.count('t a') 
2 

die die Anzahl der nicht-überlappende Vorkommen des Teils

5

Sie können durch die Verwendung eines nicht-einfangende Unter-Pattern überlappende Übereinstimmungen zu finden:

def count_overlapping(pattern, string): 
    return len(re.findall("(?=%s)" % pattern, string)) 
0

Um zu vermeiden, um eine Liste der Spiele der Schaffung eines auch re.sub mit einem abrufbaren als Ersatz verwenden. Es wird bei jeder Übereinstimmung aufgerufen, wobei der interne Zähler erhöht wird.

class Counter(object): 
    def __init__(self): 
     self.matched = 0 
    def __call__(self, matchobj): 
     self.matched += 1 

counter = Counter() 
re.sub(some_pattern, counter, text) 

print counter.matched 
Verwandte Themen