我遇到一些需要根据其中一个列表中的值进行过滤的并行列表。有时我写这样的东西来过滤它们:
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])
这会给filtered_a == (1, 2)
和filtered_b == (7, 8)
但是,将最终条件从a < 3
更改为a < 0
会导致引发异常:
Traceback (most recent call last):
...
ValueError: need more than 0 values to unpack
我知道为什么会发生这种情况:列表理解是空的,所以它就像调用zip(*[])
一样,就像zip()
一样,只返回一个无法解压缩到的空列表单独筛选filter_a和filtered_b iterables。
是否有更好(更短,更简单,更pythonic)的过滤功能来处理空箱?在空的情况下,我希望filtered_a和filtered_b是空的iterables,所以下面的代码可以保持不变。
答案 0 :(得分:4)
您可以使用默认值短路:
filtered_a, filtered_b = zip(*[(a, b) for a, b in zip(lista, listb) if a < 0]) or ([], [])
print(filtered_b, filtered_a)
# [] []
对于Python 3,你需要在list
返回的迭代器上调用zip
,这样第一个操作数就可以被计算为空列表(不是迭代器),否则默认值是由于bool(iter([]))
为True
,所以即使迭代器可能为空,也从未到达。
答案 1 :(得分:1)
我可能会做类似的事情:
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)