2013-02-11 41 views
7

Tôi đang cố định vị trí tất cả các vị trí chỉ mục của một chuỗi trong danh sách các từ và tôi muốn các giá trị được trả về dưới dạng danh sách. Tôi muốn tìm chuỗi nếu nó là của riêng nó, hoặc nếu nó được đặt trước hoặc theo sau bởi dấu câu, nhưng không phải nếu nó là một chuỗi con của một từ lớn hơn.Làm thế nào để bạn sử dụng một regex trong một danh sách hiểu trong Python?

Mã sau chỉ ghi lại "bò" và bỏ lỡ cả "kiểm tra; bò" và "bò".

myList = ['test;cow', 'one', 'two', 'three', 'cow.', 'cow', 'acow'] 
myString = 'cow' 
indices = [i for i, x in enumerate(myList) if x == myString] 
print indices 
>> 5 

Tôi đã cố gắng thay đổi mã để sử dụng một biểu thức chính quy:

import re 
myList = ['test;cow', 'one', 'two', 'three', 'cow.', 'cow', 'acow'] 
myString = 'cow' 
indices = [i for i, x in enumerate(myList) if x == re.match('\W*myString\W*', myList)] 
print indices 

Nhưng điều này mang lại một lỗi: dự kiến ​​chuỗi hoặc đệm

Nếu có ai biết những gì tôi đang làm sai tôi sẽ rất vui khi được nghe. Tôi có một cảm giác đó là một cái gì đó để làm với thực tế tôi đang cố gắng sử dụng một biểu thức chính quy trong đó khi nó mong đợi một chuỗi. Có giải pháp nào không?

Sản lượng tôi đang tìm kiếm nên đọc:

>> [0, 4, 5] 

Cảm ơn

Trả lời

14

Bạn không cần phải gán kết quả của match trở lại x. Và trận đấu của bạn phải ở trên x thay vì list.

Ngoài ra, bạn cần sử dụng re.search thay vì re.match, vì mẫu regex '\W*myString\W*' của bạn sẽ không khớp với phần tử đầu tiên. Đó là bởi vì test; không khớp với \W*. Trên thực tế, bạn chỉ cần kiểm tra ngay sau và ký tự trước, chứ không phải chuỗi hoàn chỉnh.

Vì vậy, bạn có thể sử dụng thay vì word boundaries xung quanh chuỗi:

pattern = r'\b' + re.escape(myString) + r'\b' 
indices = [i for i, x in enumerate(myList) if re.search(pattern, x)] 
4

Có một vài vấn đề với mã của bạn. Trước tiên, bạn cần phải khớp với expr đối với phần tử danh sách (x), không khớp với toàn bộ danh sách (myList). Thứ hai, để chèn một biến trong biểu thức, bạn phải sử dụng + (chuỗi nối). Và cuối cùng, sử dụng chữ thô (r'\W) đúng interpet chéo trong expr:

import re 
myList = ['test;cow', 'one', 'two', 'three', 'cow.', 'cow', 'acow'] 
myString = 'cow' 
indices = [i for i, x in enumerate(myList) if re.match(r'\W*' + myString + r'\W*', x)] 
print indices 

Nếu có cơ hội mà myString chứa các ký tự regexp đặc biệt (như một dấu gạch chéo hoặc một dấu chấm), bạn cũng sẽ cần phải áp dụng re.escape với nó:

regex = r'\W*' + re.escape(myString) + r'\W*' 
indices = [i for i, x in enumerate(myList) if re.match(regex, x)] 

Như đã chỉ ra trong các ý kiến, sau đây có thể là một lựa chọn tốt hơn:

regex = r'\b' + re.escape(myString) + r'\b' 
indices = [i for i, x in enumerate(myList) if re.search(regex, x)] 
+0

lẽ thêm 're.escape' quá? –

+0

@MartijnPieters: chắc chắn, đã thêm. – georg

+0

Điều này không khớp với phần tử đầu tiên mà OP muốn khớp. –

Các vấn đề liên quan