Handling empty case with tuple filtering and unpacking

最后都变了- 提交于 2021-02-20 09:33:23

问题


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:

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, changing the final condition from a < 3 to a < 0 causes an exception to be raised:

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

I know why this is happening: the list comprehension is empty, so it's like calling zip(*[]), which is like zip(), which just returns an empty list which cannot be unpacked into separate filtered_a and filtered_b iterables.

Is there a better (shorter, simpler, more pythonic) filtering function that handles the empty case? In the empty case, I would expect filtered_a, and filtered_b to be empty iterables so any following code could remain unchanged.


回答1:


You could simply short-circuit with 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'll need to call list on the iterator returned by zip so the first operand can be evaluated as an empty list (not an iterator), else the default value is never reached even when the iterator is potentially empty since bool(iter([])) is True.




回答2:


I'd 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)


来源:https://stackoverflow.com/questions/40468683/handling-empty-case-with-tuple-filtering-and-unpacking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!