我有一些Python字典,对于单个键,有时会有多个用逗号分隔的值(例如“ value1,value2”)。在这些情况下,我需要将字典分成多个多个值(有关所需输出的示例,请参见问题底部)。字典中每个键只能有一个值,否则它必须是一个完全独立的字典。
我试图遍历字典并在找到具有多个值的值时使用popitem函数。然后创建单独的字典并追加它们。但是我遇到了运行时错误。而且我怀疑还有其他更优雅的解决方案。
例如
x = {"name":"alice", "age":20,"hobby":"badminton, basketball", "language":"python"}
for eachkey, value in x.items():
if ", " in value:
x.popitem()
在进一步了解之前,请获取以下错误:
RuntimeError: dictionary changed size during iteration
这是预期输入和输出的示例:
输入
x = {"name":"alice", "age":20,"hobby":"badminton, basketball", "language":"python"}
输出
[
{"name":"alice", "age":20,"hobby":"badminton", "language":"python"},
{"name":"alice", "age":20,"hobby":"basketball", "language":"python"}
]
或另一个带有具有多个值的多个键的示例:
(已编辑+包括在内,以在@isaactfa回答后进行澄清)
输入
x = {"name":"alice", "age":20,"hobby":"badminton, basketball", "language":"python, go"}
输出
[
{'name': 'alice', 'age': 20, 'hobby': 'badminton', 'language': 'python'},
{'name': 'alice', 'age': 20, 'hobby': 'badminton', 'language': 'go'},
{'name': 'alice', 'age': 20, 'hobby': 'basketball', 'language': 'python'},
{'name': 'alice', 'age': 20, 'hobby': 'basketball', 'language': 'go'}
]
答案 0 :(得分:4)
我将从将输入转换为键值元组列表的列表开始(好吧)
def unwrap(d):
for k, v in d.items():
if isinstance(v, str):
yield [(k, v2.strip()) for v2 in v.split(',')]
else:
yield [(k, v)]
这样
d = {
"name": "alice",
"age": 20,
"hobby": "badminton, basketball",
"language": "python, go"
}
它将返回
[
[('name', 'alice')],
[('age', 20)],
[('hobby', 'badminton'), ('hobby', 'basketball')],
[('language', 'python'), ('language', 'go')]
]
完成此操作后,应用itertools.product
将其转换为所有可能的字典列表:
result = [
dict(x)
for x in product(*unwrap(d))
]
result
为
[
{'name': 'alice', 'age': 20, 'hobby': 'badminton', 'language': 'python'},
{'name': 'alice', 'age': 20, 'hobby': 'badminton', 'language': 'go'},
{'name': 'alice', 'age': 20, 'hobby': 'basketball', 'language': 'python'},
{'name': 'alice', 'age': 20, 'hobby': 'basketball', 'language': 'go'}
]
答案 1 :(得分:2)
您可以使用函数product()
:
from itertools import product
x = {"name":"alice", "age":20,"hobby":"badminton, basketball", "language":"python"}
vals = [v.split(', ') if isinstance(v, str) else [v] for v in x.values()]
print([dict(zip(x, p)) for p in product(*vals)])
输出:
[{'name': 'alice', 'age': 20, 'hobby': 'badminton', 'language': 'python'},
{'name': 'alice', 'age': 20, 'hobby': 'basketball', 'language': 'python'}]
答案 2 :(得分:1)
编辑:如果一个以上的键具有多个值,则这不会产生字典的所有排列。如果这是您需要的,请查看@georg的答案。
原始答案:
这应该为您提供所需的输出:
def make_dicts(x):
tuples = [(k, *(s.strip() for s in v.split(","))) if isinstance(v, str) else (k, v) for k, v in x.items()]
most_values = max(len(t) for t in tuples) - 1
for i in range(most_values):
yield {k: v[i % len(v)] for k, *v in tuples}
您现在可以遍历make_dicts(x)
来检索您的新词典,或者执行list(make_dicts(x))
将它们放在列表中。
它的工作方式是,首先创建一个元组列表,其中包含键作为第一个元素,其后每个逗号分隔的值。然后,我找到那些元组中最大的元组,因为这将创建多少个新字典(键减去1)。现在,对于每一个新字典,我都告诉它放一个键,然后放下一个值,并用模数包装索引,这样只有一个值的键就会重复。
希望这就是您想要的。