2011-07-11 4 views
12

Xin lỗi về tiêu đề, tôi không thể đưa ra một cách sạch sẽ để đặt câu hỏi của tôi.Kết hợp mẫu Python. Trận đấu 'c [bất kỳ số nào liên tiếp của a, b, hoặc c hoặc b, c, hoặc của một, vv] t'

Trong Python, tôi muốn khớp biểu thức 'c [một số thứ] t', trong đó [một số nội dung] có thể là bất kỳ số nào liên tiếp của a, b, hoặc c và theo thứ tự bất kỳ.

Ví dụ, những công việc: 'ct', 'mèo', 'cbbt', 'caaabbct', 'cbbccaat'

nhưng những điều này không: 'cbcbbaat', 'caaccbabbt'

Edit: của, của b và c của chỉ là một n ví dụ nhưng tôi thực sự muốn có thể mở rộng này để thêm chữ cái. Tôi quan tâm đến các giải pháp regex và phi regex.

+0

Có vẻ như từ phần lớn các câu trả lời rằng cách duy nhất để mã hóa điều này là tự thiết lập tất cả các trường hợp. Điều này có đúng không? Điều này sẽ rất khó nếu tôi muốn thêm hai chữ cái nữa. Tôi nghĩ rằng đó sẽ là 120 trường hợp. – Usagi

+0

"bây giờ bạn có hai vấn đề"? – geoffspear

+0

@Wooble - Không, tôi chỉ muốn giải pháp có thể mở rộng được. Hướng dẫn hoàn toàn thủ công/trực tiếp sẽ đòi hỏi rất nhiều đánh máy. – Usagi

Trả lời

6

Không chắc thế nào kèm theo bạn là để regex, nhưng đây là một giải pháp sử dụng một phương pháp khác nhau:

from itertools import groupby 

words = ['ct', 'cat', 'cbbt', 'caaabbct', 'cbbccaat', 'cbcbbaat', 'caaccbabbt'] 
for w in words: 
    match = False 
    if w.startswith('c') and w.endswith('t'): 
     temp = w[1:-1] 
     s = set(temp) 
     match = s <= set('abc') and len(s) == len(list(groupby(temp))) 
    print w, "matches" if match else "doesn't match" 

Chuỗi phù hợp nếu một bộ của các ký tự ở giữa là một tập hợp con của set('abc') và số nhóm được trả về bởi groupby() giống với số phần tử trong tập hợp.

+0

Tôi quan tâm đến cách so sánh hiệu quả. Tôi không nhất thiết phải gắn bó với regex. – Usagi

+0

Rất đẹp, và cũng dễ dàng mở rộng! Tôi đã tự viết một câu trả lời không phải là regexp, nhưng bản thân bạn thì tốt hơn nhiều, vì vậy tôi chỉ cho bạn một upvote thay vì gửi bài của tôi. –

+0

+1: dễ đọc hơn giải pháp regex. –

0

Tôi không biết động cơ regex của Python, nhưng có vẻ như bạn chỉ muốn viết 6 thứ tự có thể khác nhau trực tiếp.

/c(a*b*c*|a*c*b*|b*a*c*|b*c*a*|c*a*b*|c*b*a*)t/ 
+0

Có cách nào khác không? Nếu tôi muốn thêm d và e, ví dụ, tôi sẽ phải tự loại 120 trường hợp. – Usagi

+1

@Usagi No. Bất cứ điều gì phức tạp hơn và bạn thực sự nên mương biểu thức thông thường và phân tích nó theo cách thủ công để thay thế. –

+1

@Usagi: Bạn có thể viết một hàm tạo chuỗi regex khá dễ dàng để tránh việc nhập thủ công. – trutheality

3

Tôi tin rằng bạn cần để mã hóa một cách rõ ràng tất cả các hoán vị có thể của a s, b s và c s:

c(a*b*c*|b*a*c*|b*c*a*|c*b*a*|c*a*b*|a*c*b*)t 

Lưu ý rằng đây là một câu hỏi cực kỳ hiệu quả mà có thể quay lại rất nhiều.

+0

Nó có? Dường như với tôi rằng hầu hết các chuỗi toàn bộ có thể được analized 6 lần trước khi thất bại. Tôi không thấy bất kỳ sự bùng nổ theo cấp số nhân điển hình nào của các biểu thức có vấn đề ... – 6502

0

AFAIK không có "nhỏ gọn" cách để làm điều này ...

c(a*(b*c*|c*b*)|b*(a*c*|c*a*)|c*(a*b*|b*a*))t 
14

Không kiểm tra kỹ lưỡng, nhưng tôi nghĩ rằng điều này sẽ làm việc:

import re 

words = ['ct', 'cat', 'cbbt', 'caaabbct', 'cbbccaat', 'cbcbbaat', 'caaccbabbt'] 
pat = re.compile(r'^c(?:([abc])\1*(?!.*\1))*t$') 
for w in words: 
    print w, "matches" if pat.match(w) else "doesn't match" 

#ct matches 
#cat matches 
#cbbt matches 
#caaabbct matches 
#cbbccaat matches 
#cbcbbaat doesn't match 
#caaccbabbt doesn't match 

này phù hợp với chạy của a, b hoặc c (đó là phần ([abc])\1*), trong khi lookahead phủ định (?!.*\1) đảm bảo không có cá thể nào khác của ký tự đó xuất hiện sau khi chạy.

(chỉnh sửa: cố định một lỗi đánh máy trong lời giải thích)

+0

Làm việc như một sự quyến rũ :) – Usagi