2009-09-03 3 views
22

Pythonの正規表現の一致数を調べる方法はありますか?たとえば、文字列がある場合"It actually happened when it acted out of turn."正規表現がPythonの文字列で何回一致するかを調べる

文字列に"t a"が何回出現するか知りたいです。その文字列では、"t a"が2回表示されます。私は私の機能が2回現れたと私に伝えたい。これは可能ですか?

+0

重複するマッチをカウントする必要がありますか?文字列「友人の友人」の正規表現「友人の友人」は1回か2回ですか? –

+0

重複が必要です。 – Dan

+2

重複が必要ですか?したがって、一致パターンが "aa"で、ソース文字列が "aaaa"の場合、正解は3ですか? – steveha

答えて

16

既存のソリューションの非重複出現数を返す

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

は、非オーバーラップマッチのための罰金です(そしておそらく試合の膨大な数を除き、間違いなく最適) sum(1 for m in re.finditer(thepattern, thestring))のような代替案(あなたが心配しているときにリストを実体化するのを避けるため)もかなり可能です。 ...やや特異なsubnを使用し、結果の文字列を無視することになります。

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

あなたが唯一の100試合まで(例えば)カウントするように世話をしている場合、この後者の考え方の唯一の本当の利点が来るでしょう。 re.subn(pattern, '', thestring, 100)[1]が実用的かもしれません(100件の一致、または1000以上の数字があるかどうかにかかわらず100を返します)。

カウンティングをマッチさせるには、問題の組み込み関数がすべて非重複マッチングに焦点を合わせているため、より多くのコードを記述する必要があります。パターンが'a+'で、文字列が'aa'であるなど、定義に問題があります。これは1つの一致、または3つ(最初のa、どちらも2番目)、または...とみなされますか?あなたが

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() 

注:あなたが(そして、前の段落に例えば2本のマッチを与えるだろう)文字列で明確なスポットで始まるマッチを、おそらくオーバーラップしたいと仮定すると、例えば

関数re.searchstart引数(検索の開始位置)を受け入れません。メソッドsearchのように、パターンをREオブジェクトにコンパイルする必要があります。したがって、あなたが行くときに文字列をスライスする必要があります。確かに次の検索をするよりももっと努力する私はこの機能でやっている次の可能な別個の出発点で触れます。

6

これを試しましたか?

len(pattern.findall(source)) 
+1

それは見つかっても – cobbal

+0

それを修正していただきありがとうございます! –

+0

これは重複してカウントされますか?彼はそれをサポートする必要があると言いました。 (実際に実行するのは難しいと思われます) –

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

偉大な仕事!ありがとう –

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

私は、これは正規表現についての質問です知っています。私はちょうど誰かが非正規表現の解決策を望んでいるなら、私が将来の参照のためにcountメソッドを言及したいと思った。 findallに基づくサブ

5

あなたは非キャプチャサブパターンを使って、試合を重ねる見つけることができます:

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

は1にも置き換えとして呼び出し可能でre.subを使用することができますマッチのリストを作成しないようにします。各マッチで呼び出され、内部カウンタをインクリメントします。

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 
関連する問題