具有可变填充值的Python itertools.zip_longest

问题描述 投票:0回答:2

在评估网络响应的代码中,我想从多个列表中压缩元素。然而,迭代器的元素是

dict
的。 因此,我想用
dict
来填充缺失值,但每个生成的元素都应该有它自己的
dict
实例。

以下代码按

itertools.zip_longest
对每个列表中的元素进行分组。 只要指定了不可变的
fillvalue
,就没有问题。

import collections
import itertools

l1 = [{"a": 100}, {"b": 200}, {"c": 300}]
l2 = [{"d": 400}]

ll = list(itertools.zip_longest(l1, l2, fillvalue=0))
print(ll)

->

[({'a': 100}, {'d': 400}), ({'b': 200}, 0), ({'c': 300}, 0)]

现在,当指定一个可变的

fillvalue
时,所有
fillvalue
共享同一个实例,因此更改一个实例就会更改所有实例:

import collections
import itertools

l1 = [{"a": 100}, {"b": 200}, {"c": 300}]
l2 = [{"d": 400}]

ll = list(itertools.zip_longest(l1, l2, fillvalue=dict()))
ll[1][1]["x"] = 150
print(ll)

->

[({'a': 100}, {'d': 400}), ({'b': 200}, {'x': 150}), ({'c': 300}, {'x': 150})]

为了防止所有字典共享同一个实例,我使用了

copy.deepcopy

import collections
import copy
import itertools

l1 = [{"a": 100}, {"b": 200}, {"c": 300}]
l2 = [{"d": 400}]

ll = list(itertools.zip_longest(l1, l2, fillvalue=copy.deepcopy(dict())))
ll[1][1]["x"] = 150
print(ll)

->

[({'a': 100}, {'d': 400}), ({'b': 200}, {'x': 150}), ({'c': 300}, {'x': 150})]

因此,来自

dict
的所有
fillvalue
仍然共享同一个实例。

我想补充一点,假设填充值为

ll = [item or dict() for item in itertools.zip_longest(l1, l2)]
None
都不起作用。

那么,我怎样才能让每个

fillvalue
独一无二呢?

python python-3.x python-itertools default-value mutable
2个回答
2
投票

您可以使用哨兵值并将

zip_longest
包装在另一个管道中。

例如:

sentinel = object()
l = list(tuple({} if x is sentinel else x for x in items) for items in zip_longest(l1, l2, fillvalue=sentinel))

对于此示例,您可以使用

None
而不是自定义
sentinel
对象。


1
投票

您无法教

zip_longest
为您复制
dict
。您必须自己复制它们(这也会使原始值与
l2
分离),例如:

ll = [(d1, d2.copy()) for d1, d2 in itertools.zip_longest(l1, l2, fillvalue={})]

或者只是根据需要从头开始制作它们(这会将空的

dict
l2
分离,留下其余的别名,这可能是也可能不是您想要的):

ll = [(d1, d2 or {}) for d1, d2 in itertools.zip_longest(l1, l2, fillvalue=False)]

完美保留别名的替代方案会更冗长:

ll = [(d1, {} if d2 is None else d2) for d1, d2 in itertools.zip_longest(l1, l2, fillvalue=None)]

如果

l1
可能比
l2
短,您可以对每个列表组件中的
d1
应用类似的转换。

© www.soinside.com 2019 - 2024. All rights reserved.