2012-03-26 37 views
205

Cách nào là cách thanh lịch và hiệu quả nhất để tìm/trả lại mục danh sách đầu tiên khớp với một tiêu chí nhất định?tìm mục đầu tiên khớp với tiêu chí

Ví dụ: nếu tôi có danh sách đối tượng và tôi muốn lấy đối tượng đầu tiên của những đối tượng có thuộc tính obj.val==5. Tôi tất nhiên có thể sử dụng danh sách hiểu, nhưng điều đó sẽ phải chịu O (n) và nếu n là lớn, nó lãng phí. Tôi cũng có thể sử dụng một vòng lặp với break khi tiêu chí đã được đáp ứng, nhưng tôi nghĩ rằng có thể có một giải pháp nhiều hơn/thanh lịch hơn.

+2

gì xảy ra nếu bạn muốn nhận được các mục và chỉ số? –

+1

@CharlieParker, để lấy cả chỉ mục và mục, sử dụng liệt kê() - tiếp theo ((idx, obj) cho idx, obj trong liệt kê (objs) nếu obj.val == 5) –

Trả lời

367

Nếu bạn không có bất kỳ chỉ số khác hoặc thông tin được sắp xếp cho các đối tượng của bạn, sau đó bạn sẽ phải lặp lại cho đến khi một đối tượng như vậy được tìm thấy:

next(obj for obj in objs if obj.val==5) 

Tuy nhiên điều này là nhanh hơn so với một sự hiểu biết danh sách đầy đủ. Hãy so sánh hai:

[i for i in xrange(100000) if i == 1000][0] 

next(i for i in xrange(100000) if i == 1000) 

Người đầu tiên cần 5.75ms (nhanh hơn 100 lần vì vòng lặp 100 lần ngắn hơn), thứ hai một 58.3μs.

+93

'next' cũng cung cấp' đối số mặc định', trong trường hợp không tồn tại đối tượng nào. Ví dụ. 'next ((i cho i trong phạm vi (500) nếu i> 600), 600)' sẽ trả lại 600. – Darthfett

+22

Python [** 'next()' **] (http://docs.python.org/2 /library/functions.html#next) –

+5

Vâng, đây là nó, nhưng tôi chỉ mong đợi câu trả lời đúng để trông mát hơn. Chúng tôi luôn quảng cáo trăn để trở nên thanh lịch. Nếu bạn muốn nó mạnh mẽ, bạn nên cung cấp 'default' (ví dụ' None') - và sau đó bạn không cần quên rằng 'Biểu thức Generator phải được ngoặc đơn nếu không phải là đối số duy nhất' ... Vâng, điều này ảnh hưởng đến khả năng đọc như thế nào ? Ví dụ. đầu tiên không đường dẫn arugment: 'next ((arg cho arg trong sys.argv nếu không os.path.exists (arg)), None)' - không phải là rất thân thiện. –

2
a=[100,200,300,400,500] 
def search(b): 
try: 
    k=a.index(b) 
    return a[k] 
except ValueError: 
    return 'not found' 
print(search(500)) 

nó sẽ trả lại đối tượng nếu tìm thấy người nào khác nó sẽ trả lại "không tìm thấy"

+0

Điều này thật tuyệt, nhưng chỉ hoạt động khi tiêu chí là so sánh với mục danh sách. Tôi đang tìm một giải pháp chung chung hơn để xử lý phạm vi lựa chọn rộng hơn – Jonathan

+0

nhưng @Jonathan trong câu hỏi của bạn mà bạn đã đề cập ** cách hiệu quả để tìm \ trả về mục danh sách đầu tiên ** vì vậy danh sách trên a = [100,200,300,400,500] có thể chứa bất kỳ loại đối tượng không chỉ là số. –

+1

và tôi kết luận câu với "... phù hợp với một tiêu chí nhất định", không giống như đối sánh về tính bình đẳng hoặc danh tính :) Tôi đã +1 khi tôi nghĩ giải pháp của bạn tốt cho trường hợp riêng tư – Jonathan

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