我有一个任意的python字典x
,这样每个键的值本身就是一个列表。这是一个例子:
x = {"first_name": ["Habib", "Wen-lao"], "second_name": ["Khan", "Chen"]}
鉴于x
,我想编写一个计算字典列表的方法,使每个字典具有与x相同的键,但值是每个列表元素的组合。
此外,我希望看到完全省略键的所有组合。
所以在这种情况下,结果应该是:
[{"first_name": "Habib", "second_name": "Khan"},
{"first_name": "Habib", "second_name": "Chen"},
{"first_name": "Habib"},
{"first_name": "Wen-lao", "second_name": "Khan"},
{"first_name": "Wen-lao", "second_name": "Chen"}
{"first_name": "Wen-lao"},
{"second_name": "Khan"},
{"second_name": "Chen"},
{}]
我该怎么办?字典x
可以具有任意数量的具有任意名称的键。结果列表的排序与我无关。
目前我有这个:
>>> from collections import OrderedDict
>>> from itertools import product
>>>
>>> def looper(in_dict):
>>> order_of_keys = in_dict.keys()
>>> list_of_tuples = [(key, in_dict[key]) for key in order_of_keys]
>>> ordered_dict = OrderedDict(list_of_tuples)
>>> return [dict(zip(ordered_dict.keys(), t)) for t in product(*ordered_dict.values())]
>>>
>>> x = {"first_name": ["Habib", "Wen-lao"], "second_name": ["Khan", "Chen"]}
>>> print looper(in_dict=x)
[{'first_name': 'Habib', 'second_name': 'Khan'},
{'first_name': 'Habib', 'second_name': 'Chen'},
{'first_name': 'Wen-lao', 'second_name': 'Khan'},
{'first_name': 'Wen-lao', 'second_name': 'Chen'}]
但它没有显示省略键的组合。 我怎么能这样做?
编辑: 这question是相关的,但却有很大的不同。在那里,我想知道如何创建所有列表的简单组合。在这里,我想知道如何包含省略键的组合。
答案 0 :(得分:2)
itertools
不会处理集合中的 epsilon 元素;您需要将其作为每个集合中的单独子句进行编码。对每个集合添加一个关键元素,例如epsilon: None
;在您的理解表达式中,您需要添加if
子句来忽略任何此类元素,而不是将其包含在输出中。请注意,zip
将不再提供,因为您要生成不同长度的条目。
另一种可能性是压缩列表,包括epsilon元素,但写一个表达式以从zip
ped列表的成员中排除这些元素。
你能从那里拿走吗?
答案 1 :(得分:2)
我们首先将词典的值列表中的每个名称与其键组合在一起,将这些结果保存到y
列表中。接下来,我们使用z
创建所需对的列表itertools.product
。然后,我们使用z
中的个人名称扩展y
。最后,我们向z
from itertools import product
x = {"first_name": ["Habib", "Wen-lao"], "second_name": ["Khan", "Chen"]}
y = [[(k, u) for u in v] for k, v in x.items()]
z = [dict(t) for t in product(*y)]
z.extend({k: v} for u in y for k, v in u)
z.append({})
for row in z:
print(row)
<强>输出强>
{'first_name': 'Habib', 'second_name': 'Khan'}
{'first_name': 'Habib', 'second_name': 'Chen'}
{'first_name': 'Wen-lao', 'second_name': 'Khan'}
{'first_name': 'Wen-lao', 'second_name': 'Chen'}
{'first_name': 'Habib'}
{'first_name': 'Wen-lao'}
{'second_name': 'Khan'}
{'second_name': 'Chen'}
{}
如果x
列表包含两个以上的项目,并且每个x
值列表中的子列表包含的项目超过2个,则此代码将给出正确的结果。
答案 2 :(得分:2)
我试着写尽可能少的变化。因为你从无序的dict开始,将它转换为orderedDict不会带来任何东西。不过,您可以确定dict.keys()
和dict.values()
are in the same order。
您只需要为每个值列表添加None
,然后删除值为None
的对:
from itertools import product
def looper(in_dict):
keys = in_dict.keys()
values = [l + [None] for l in in_dict.values()]
return [{k: v for k,v in zip(keys, t) if v} for t in product(*values)]
x = {"first_name": ["Habib", "Wen-lao"], "second_name": ["Khan", "Chen"]}
for d in looper(x):
print(d)
输出:
{'first_name': 'Habib', 'second_name': 'Khan'}
{'first_name': 'Habib', 'second_name': 'Chen'}
{'first_name': 'Habib'}
{'first_name': 'Wen-lao', 'second_name': 'Khan'}
{'first_name': 'Wen-lao', 'second_name': 'Chen'}
{'first_name': 'Wen-lao'}
{'second_name': 'Khan'}
{'second_name': 'Chen'}
{}