如何编写python方法来生成列表组合,还有这个添加的约束?

时间:2017-11-08 16:26:53

标签: python python-2.7 dictionary

我有一个任意的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是相关的,但却有很大的不同。在那里,我想知道如何创建所有列表的简单组合。在这里,我想知道如何包含省略键的组合。

3 个答案:

答案 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'}
{}