2016-11-07 11 views
6

Tôi có một tình huống với một số danh sách song song cần được lọc dựa trên các giá trị trong một trong các danh sách. Đôi khi tôi viết một cái gì đó như thế này để lọc chúng:Xử lý trường hợp trống với lọc tuple và giải nén

lista = [1, 2, 3] 
listb = [7, 8, 9] 
filtered_a, filtered_b = zip(*[(a, b) for (a, b) in zip(lista, listb) if a < 3]) 

Điều này cho phép filtered_a == (1, 2)filtered_b == (7, 8)

Tuy nhiên, việc thay đổi điều kiện cuối cùng từ a < 3 để a < 0 gây một ngoại lệ được nâng lên:

Traceback (most recent call last): 
    ... 
ValueError: need more than 0 values to unpack 

Tôi biết lý do tại sao điều này xảy ra: danh sách hiểu là trống, vì vậy nó giống như gọi số zip(*[]), giống như zip(), mà chỉ cần retur ns một danh sách rỗng không thể được giải nén thành các filter_a và filter_b iterables riêng biệt.

Có chức năng lọc tốt hơn (ngắn hơn, đơn giản hơn, phù hợp hơn) để xử lý trường hợp trống không? Trong trường hợp trống, tôi mong đợi filter_a, và filter_b là các vòng lặp trống nên bất kỳ mã nào sau đây có thể không thay đổi.

+1

Bạn mong đợi điều gì về 'filter_a' và' filtering_b' trong trường hợp này? 'Không'? Tuples/danh sách rỗng? –

+0

@TomDalton - Quên điều đó, cảm ơn. Đã thêm vào câu hỏi ngay bây giờ: "Trong trường hợp trống, tôi mong đợi filter_a và filter_b là các vòng lặp trống nên bất kỳ mã nào sau đây có thể vẫn không thay đổi". – Justin

Trả lời

4

Bạn có thể chỉ đơn giản là ngắn mạch với các giá trị mặc định:

filtered_a, filtered_b = zip(*[(a, b) for a, b in zip(lista, listb) if a < 0]) or ([], []) 
print(filtered_b, filtered_a) 
# [] [] 

Đối với Python 3, bạn sẽ cần phải gọi list trên trình vòng lặp được trả về bởi zip do đó toán hạng đầu tiên có thể được đánh giá dưới dạng danh sách trống (không phải là trình lặp), nếu không giá trị mặc định sẽ không bao giờ đạt được ngay cả khi trình lặp có khả năng trống kể từ bool(iter([]))True.

1

tôi có lẽ muốn làm điều gì đó như:

lista = [1, 2, 3] 
listb = [7, 8, 9] 

filtered_abs = ((a, b) for (a, b) in zip(lista, listb) if a < 3]) 

for a, b in filtered_abs: 
    do_thing(a, b) 
Các vấn đề liên quan