2012-06-19 16 views
35

Lấy cảm hứng từ câu hỏi đã bị xóa; cho một regex với các nhóm được đặt tên, có phương pháp như findall trả về danh sách dict với các nhóm chụp được đặt tên thay vì danh sách tuple không?re.findall trả về một mệnh đề của các nhóm chụp được đặt tên?

Given:

>>> import re 
>>> text = "bob sue jon richard harry" 
>>> pat = re.compile('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)') 
>>> pat.findall(text) 
[('bob', 'sue'), ('jon', 'richard')] 

thay vì nên cung cấp cho:

[{'name': 'bob', 'name2': 'sue'}, {'name': 'jon', 'name2': 'richard'}] 

Trả lời

71
>>> import re 
>>> s = "bob sue jon richard harry" 
>>> r = re.compile('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)') 
>>> [m.groupdict() for m in r.finditer(s)] 
[{'name2': 'sue', 'name': 'bob'}, {'name2': 'richard', 'name': 'jon'}] 
+0

Đây là một giải pháp tốt hơn nhiều so với phiên bản của tôi, mà tập trung vào việc sử dụng 'findall' từ get-go. – beerbajay

+0

Điều này rất hữu ích, cảm ơn! – mVChr

1

Không có built-in phương pháp để làm điều này, nhưng kết quả dự kiến ​​có thể đạt được bằng cách sử dụng comprehensions danh sách.

[dict([[k, i if isinstance(i, str) else i[v-1]] for k,v in pat.groupindex.items()]) for i in pat.findall(text)] 

Với định dạng thân thiện:

>>> [ 
...  dict([ 
...   [k, i if isinstance(i, str) else i[v-1]] 
...   for k,v in pat.groupindex.items() 
...  ]) 
...  for i in pat.findall(text) 
... ] 

Chúng tôi xây dựng một danh sách sử dụng một danh sách hiểu, lặp qua kết quả từ findall đó là hoặc là một danh sách các chuỗi hoặc một danh sách các hàng (0 hoặc 1 chụp các nhóm dẫn đến danh sách str).

Đối với mỗi mục trong kết quả chúng ta xây dựng một dict từ một sự hiểu biết danh sách đó được tạo ra từ groupindex lĩnh vực mô hình biên soạn, trông giống như:

>>> pat.groupindex 
{'name2': 2, 'name': 1} 

Một danh sách được xây dựng cho từng hạng mục trong groupindex và nếu mục từ findall là một bộ, số nhóm từ groupindex được sử dụng để tìm đúng mục, nếu không mục đó được gán cho nhóm chỉ có tên.

[k, i if isinstance(i, str) else i[v-1]] 

Cuối cùng, một dict được tạo từ danh sách các chuỗi.

Lưu ý rằng groupindex chỉ chứa các nhóm được đặt tên, do đó các nhóm chụp không được đặt tên sẽ bị bỏ qua từ kết quả dict.

Và kết quả:

[dict([[k, i if isinstance(i, str) else i[v-1]] for k,v in pat.groupindex.items()]) for i in pat.findall(text)] 
[{'name2': 'sue', 'name': 'bob'}, {'name2': 'richard', 'name': 'jon'}] 
9

bạn có thể chuyển sang finditer

>>> import re 
>>> text = "bob sue jon richard harry" 
>>> pat = re.compile('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)') 
>>> for m in pat.finditer(text): 
...  print m.groupdict() 
... 
{'name2': 'sue', 'name': 'bob'} 
{'name2': 'richard', 'name': 'jon'} 
3

Nếu bạn đang sử dụng phù hợp:

r = re.match('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)', text) 
r.groupdict() 

documentation here

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