使用元组过滤和拆包处理空情况
Handling empty case with tuple filtering and unpacking
我遇到一些并行列表需要根据其中一个列表中的值进行过滤的情况。有时我会写这样的东西来过滤它们:
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()
,只是 returns 一个空列表,不能解压到单独的 filtered_a 和 filtered_b 迭代器中。
是否有更好的(更短、更简单、更pythonic)处理空案例的过滤函数?在空的情况下,我希望 filtered_a 和 filtered_b 是空的可迭代对象,因此任何后续代码都可以保持不变。
我可能会这样做:
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)
您可以使用默认值 短路:
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_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()
,只是 returns 一个空列表,不能解压到单独的 filtered_a 和 filtered_b 迭代器中。
是否有更好的(更短、更简单、更pythonic)处理空案例的过滤函数?在空的情况下,我希望 filtered_a 和 filtered_b 是空的可迭代对象,因此任何后续代码都可以保持不变。
我可能会这样做:
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)
您可以使用默认值 短路:
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
.