Handling an empty case by filtering and unpacking tuples

I have a situation with some parallel lists that need to be filtered based on the values ​​in one of the lists. Sometimes I write something like this to filter them out:

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]) 

This gives filtered_a == (1, 2) and filtered_b == (7, 8)

However, a change in the final condition from a < 3 to a < 0 leads to an exception:

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

I know why this happens: the list comprehension is empty, so he likes to call zip(*[]) , which is similar to zip() , which simply returns an empty list that cannot be unpacked into separate iterations of filter_a and filter_b.

Is there a better (shorter, simpler, more Python) filtering function that handles an empty case? In the empty case, I would expect filter_a and filters_b to be empty iterators, so any following code may remain unchanged.

+6
source share
2 answers

You can simply short-circuit the default values:

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

For Python 3, you need to call list on the iterator returned by zip so that the first operand can be evaluated as an empty list (not an iterator), otherwise the default value will never be reached even if the iterator is potentially empty, since bool(iter([])) is True .

+4
source

I would probably do something like:

 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) 
+1
source

Source: https://habr.com/ru/post/1012110/


All Articles