2010-03-12 24 views
37

Tôi có một chức năng để chọn ra cục u từ một danh sách các chuỗi và trả lại như một danh sách khác:Làm thế nào để sử dụng lại đối tượng phù hợp trong một sự hiểu biết danh sách

def filterPick(lines,regex): 
    result = [] 
    for l in lines: 
     match = re.search(regex,l) 
     if match: 
      result += [match.group(1)] 
    return result 

Có cách nào để tái cấu trúc này như một danh sách bao quát? Rõ ràng nó khá rõ ràng; chỉ tò mò thôi.


Nhờ những người đã đóng góp, đề cập đặc biệt đến @Alex. Đây là một phiên bản cô đọng của những gì tôi đã kết thúc; phương pháp phù hợp với regex được chuyển cho filterPick như là một "tiền treo" tham số:

import re 

def filterPick(list,filter): 
    return [ (l, m.group(1)) for l in list for m in (filter(l),) if m] 

theList = ["foo", "bar", "baz", "qurx", "bother"] 
searchRegex = re.compile('(a|r$)').search 
x = filterPick(theList,searchRegex) 

>> [('bar', 'a'), ('baz', 'a'), ('bother', 'r')] 

Trả lời

66
[m.group(1) for l in lines for m in [regex.search(l)] if m] 

Các "lừa" là phần for m in [regex.search(l)] - đó là cách bạn "gán" một giá trị mà bạn cần phải sử dụng nhiều hơn một lần, trong một danh sách hiểu - chỉ cần thêm một mệnh đề như vậy, trong đó đối tượng "lặp" qua một danh sách một mục có chứa một giá trị bạn muốn "gán" cho nó. Một số người cho rằng điều này không rõ ràng về mặt phong cách, nhưng đôi khi tôi thấy nó thực tế.

+1

Alex, tôi thích điều đó; cảm ơn và +1. Tôi có một số nâng khá nặng để làm với mã này - tôi nên lo lắng về chi phí phụ của thiết lập và xé xuống "iterator giả"? BTW Tôi đăng ký học thuyết "tối ưu hóa sau". –

+1

@Brent, "trình lặp giả" sẽ không đáng kể wrt cuộc gọi tìm kiếm; một tối ưu hóa nhỏ là sử dụng '(regex.search (l),)' thay cho '[regex.search (l)]' (mà tôi thấy dễ đọc hơn nhưng chậm hơn - tôi nghĩ bạn không thể trong một vội vàng như bạn đã thực sự gọi hàm 're.search' từ mô-đun chứ không phải là phương thức của đối tượng re. Kéo' regex.search' như là một phương thức ràng buộc bên ngoài listcomp là một tối ưu hóa nhỏ nhưng hữu ích khác, btw. –

+0

ngay sau khi tôi nhìn thấy câu trả lời của bạn tôi nhận ra rằng bằng cách sử dụng re.search không phải là cách tốt nhất để đi.Bạn có thể làm rõ cho tôi như thế nào bạn sẽ "[kéo] regex.search như một phương pháp ràng buộc bên ngoài của listcomp"? Tôi thực sự đánh giá cao sự kiên nhẫn của bạn với một listcomp và Python noob –

9
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m] 
7

Nó có thể được rút ngắn một chút

def filterPick(lines, regex): 
    matches = map(re.compile(regex).match, lines) 
    return [m.group(1) for m in matches if m] 

Bạn có thể đặt nó tất cả trong một dòng, nhưng điều đó có nghĩa là bạn sẽ phải phù hợp với mỗi dòng hai lần đó sẽ là một chút ít hiệu quả.

+2

Không, không cần phải khớp với mỗi dòng hai lần, hãy xem câu trả lời của tôi. –

+0

Thật vậy, câu trả lời của bạn là sạch hơn nhiều, +1 từ tôi :) – Wolph

-13
>>> "a" in "a visit to the dentist" 
True 
>>> "a" not in "a visit to the dentist" 
False 

Đó cũng làm việc với một truy vấn tìm kiếm bạn đang truy lùng trong một danh sách

'P = 'a', 'b', 'c'

'b' trong P` trả về true

+1

Làm thế nào để trả lời câu hỏi? –

+0

Câu hỏi này có thể trình bày một cách tốt hơn để kiểm tra đầu vào vào danh sách hơn là lại, nhưng bằng cách này không hoạt động nếu bạn không kết quả grep. U luôn luôn có thể làm một vòng lặp đơn giản cho xung quanh đầu ra lại. Không có nhiều khác biệt để làm điều đó bằng tay hơn là sử dụng một chức năng mà làm như vậy ... – erm3nda

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