我有一个字典,其中一个键的值为列表
example = {"a":1,"b":[1,2]}
我正在尝试解压 example["b"]
并使用单独的 example["b"]
值创建相同字典的列表。
output = [{"a":1,"b":1},{"a":1,"b":2}]
我尝试使用 for 循环来理解 dict 列表的解包和重建,但我看到了一个奇怪的行为 - 可能是我在这里遗漏了一些简单的东西......
iter = example.get("b")
new_list = []
for p in iter:
print(f"p is {p}")
tmp_dict = example
tmp_dict["b"] = p
print(tmp_dict)
new_list.append(tmp_dict)
print(new_list)
输出
p is 1
{'a': 1, 'b': 1}
p is 2
{'a': 1, 'b': 2}
[{'a': 1, 'b': 2}, {'a': 1, 'b': 2}]
为什么列表中的第一个字典被分配为 example["b"] = 2
尽管第一个 print()
显示 p 是 1
?
最佳答案
Why is the first dict in the list gets assigned with example["b"] = 2 although the first print() shows that p is 1
因为它们都是相同的字典:example
。如果您在循环内print(id(tmp_dict))
,您可以看到这一点,并且您将看到它始终是同一个对象。请参阅What is the id( ) function used for? (这是一个 python 2 问题,但也适用于 python 3)
如果您想保留代码,只需从 example
创建一个新字典并将其分配给 tmp_dict
即可。请参阅How to copy a dictionary and only edit the copy
tmp_dict = example.copy()
虽然这基本上复制了整个字典只是为了丢弃 b
键,所以你可以简单地这样做:
tmp_dict = {"a": example["a"]}
请注意,不建议使用 iter
作为变量名称,因为 iter
已经 means something in python
相反,这是一种适用于所有情况的通用方法,无需对任何键进行硬编码。 让我们首先创建一个临时字典,其中所有值都是列表。
temp = {k: v if isinstance(v, list) else [v] for k, v in example.items()}
这使我们能够以列表的形式获取 temp
字典中所有值的列表。
我们想要这个 temp
字典中所有值的乘积。为此,我们可以使用 itertools.product 函数和 unpack我们的列表列表及其参数。
在每次迭代中,生成的元组将具有 temp
字典的每个键一个值,因此我们需要做的就是 zip
与我们的元组一起使用,并从这些键值对中创建一个字典。这给了我们列表元素!
import itertools
keys = list(temp.keys())
vals = list(temp.values())
result = []
for vals_product in itertools.product(*vals):
d = dict(zip(keys, vals_product))
result.append(d)
这给出了所需的结果:
[{'a': 1, 'b': 1}, {'a': 1, 'b': 2}]
这甚至适用于具有更多键的示例
:
example = {'a': 1, 'b': [1, 2], 'c': [1, 2, 3]}
给出:
[{'a': 1, 'b': 1, 'c': 1},
{'a': 1, 'b': 1, 'c': 2},
{'a': 1, 'b': 1, 'c': 3},
{'a': 1, 'b': 2, 'c': 1},
{'a': 1, 'b': 2, 'c': 2},
{'a': 1, 'b': 2, 'c': 3}]
关于python - 从带有具有列表值的键的字典创建一个新的字典列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74106192/