我有一些并行列表的情况,需要根据其中一个列表中的值进行过滤。有时我写这样的东西来过滤它们:
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()
一样,只是返回一个空列表,不能解压缩成单独的filtered_a和filtered_b可迭代对象。
是否有更好的(更短、更简单、更python化的)过滤函数来处理空情况?在空的情况下,我希望filtered_a和filtered_b是空的可迭代对象,因此下面的代码可以保持不变。
您可以简单地使用短路的默认值:
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,您需要在zip
返回的迭代器上调用list
,以便第一个操作数可以作为空列表(而不是迭代器)求值,否则即使迭代器可能为空,也不会达到默认值,因为bool(iter([]))
是True
。
我可能会这样做:
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)