通过元组过滤和拆包处理空情况



我有一些并行列表的情况,需要根据其中一个列表中的值进行过滤。有时我写这样的东西来过滤它们:

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)

最新更新