2009-09-03 58 views
22

Có cách nào mà tôi có thể tìm ra bao nhiêu kết hợp của một regex trong một chuỗi trong Python? Ví dụ: nếu tôi có chuỗi "It actually happened when it acted out of turn."Tìm ra bao nhiêu lần một regex phù hợp trong một chuỗi trong Python

Tôi muốn biết số lần "t a" xuất hiện trong chuỗi. Trong chuỗi đó, "t a" xuất hiện hai lần. Tôi muốn chức năng của tôi cho tôi biết nó xuất hiện hai lần. Điều này có thể không?

+0

Bạn có cần tính các kết quả trùng lặp không? Là regex "bạn của một người bạn" một hoặc hai lần trong chuỗi "bạn của một người bạn của một người bạn"? –

+0

Tôi cần chồng chéo. – Dan

+2

Bạn cần chồng chéo? Vì vậy, nếu mẫu khớp là "aa" và chuỗi nguồn là "aaaa" thì câu trả lời đúng là 3? – steveha

Trả lời

16

Các giải pháp hiện tại dựa trên findall cũng tốt cho trận đấu không chồng chéo (và không có nghi ngờ tối ưu trừ có thể cho số lượng lớn các trận đấu), mặc dù lựa chọn thay thế như sum(1 for m in re.finditer(thepattern, thestring)) (để tránh bao giờ thực hiện danh sách khi tất cả các bạn quan tâm là đếm) cũng khá tốt. Hơi mang phong cách riêng sẽ được sử dụng subn và bỏ qua chuỗi kết quả ...:

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

lợi thế thực duy nhất của ý tưởng sau này sẽ đến nếu bạn chỉ quan tâm để đếm (nói) lên đến 100 trận đấu; sau đó, re.subn(pattern, '', thestring, 100)[1] có thể thực tế (trả lại 100 cho dù có 100 kết quả phù hợp hoặc 1000 hoặc thậm chí là số lớn hơn).

Đếm chồng chéo kết quả phù hợp yêu cầu bạn viết nhiều mã hơn, bởi vì các hàm tích hợp được đề cập đều tập trung vào các kết quả trùng lặp không trùng lặp. Ngoài ra còn có vấn đề về định nghĩa, ví dụ: với mẫu là 'a+' và tham gia là 'aa', bạn có cho rằng đây chỉ là một kết quả phù hợp hay ba (số a đầu tiên, thứ hai, cả hai) hoặc ...?

Giả sử ví dụ mà bạn muốn có thể chồng chéo trận bắt đầu tại các điểm khác nhau trong chuỗi (mà sau đó sẽ cung cấp cho HAI trận ví dụ như trong đoạn trước):

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

Lưu ý rằng bạn làm phải biên dịch mẫu thành đối tượng RE trong trường hợp này: hàm re.search không chấp nhận đối số start (vị trí bắt đầu cho tìm kiếm) theo cách phương thứcsearch, vì vậy bạn phải cắt bớt lời khi bạn đi - chắc chắn nhiều nỗ lực hơn là chỉ tìm kiếm tiếp theo tart tại điểm bắt đầu có thể khác biệt tiếp theo, đó là những gì tôi đang làm trong chức năng này.

6

Bạn đã thử điều này chưa?

len(pattern.findall(source)) 
+1

đó là findall mặc dù – cobbal

+0

Cảm ơn bạn đã sửa chữa nó! –

+0

Số này có trùng lặp không? Anh ta nói nó cần hỗ trợ điều đó. (Có vẻ như điều đó sẽ thực sự khó thực hiện) –

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

Chúc mừng tuyệt vời !!! thanks –

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

Tôi biết đây là một câu hỏi về regex. Tôi chỉ nghĩ rằng tôi muốn đề cập đến phương pháp count để tham khảo trong tương lai nếu ai đó muốn có giải pháp không phải là regex.

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

nào trả lại số lần xuất hiện không chồng chéo của các chuỗi

5

Bạn có thể tìm chồng chéo trận đấu bằng cách sử dụng một subpattern noncapturing:

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

Để tránh tạo ra một danh sách các trận đấu người ta cũng có thể sử dụng re.sub với một callable để thay thế. Nó sẽ được gọi trên mỗi trận đấu, tăng bộ đếm nội bộ.

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 
Các vấn đề liên quan