如何在Python中从列表字典的值生成所有组合

37

我想生成一个字典中所有列表值的组合:

{'A':['D','E'],'B':['F','G','H'],'C':['I','J']}

每次,每个字典条目中的一个项目将被选中并与其他键的项目组合,因此我有:

['D','F','I']
['D','F','J']
['D','G','I']
['D','G','J']
['D','H','I']
...
['E','H','J']

我知道在itertools 中有一些用于生成列表中项目组合的功能,但是由于我有不同的"value池",所以我认为无法在这里使用它。

是否有现成的解决方案可以做到这一点,或者我该如何自己处理,我对这个嵌套结构感到非常困惑。


2
那么你应该尝试编写代码来实现,如果遇到问题再回来。 - Scott Hunter
8
itertools.product(*yourdict.values()) - Phillip
2
字典是无序的!请澄清。 - Karoly Horvath
1
我试图编写代码,但卡住了,实际上我正在寻找现有的解决方案,以免在此浪费时间... 我不明白为什么你说字典是无序的,我知道这一点,但这与我的问题无关,我想要组合,而不是排列。 @Phillip:谢谢,我正在尝试。 - ibi0tux
你假设了一个顺序。为什么是D作为第一个字母,而不是...比如说F - Karoly Horvath
显示剩余2条评论
5个回答

59
如果你想在排列中保留 key:value,可以使用:
import itertools
keys, values = zip(*my_dict.items())
permutations_dicts = [dict(zip(keys, v)) for v in itertools.product(*values)]

这将为您提供具有排列顺序的字典列表:

print(permutations_dicts)
[{'A':'D', 'B':'F', 'C':'I'}, 
 {'A':'D', 'B':'F', 'C':'J'},
 ...
 ]

免责声明:这并不是OP所要求的内容,但是我通过谷歌搜寻到了这里。如果你想获取OP所要求的内容,只需在列表推导式中删除dict部分即可,即

permutations_dicts = [v for v in itertools.product(*values)]

46
import itertools as it

my_dict={'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
allNames = sorted(my_dict)
combinations = it.product(*(my_dict[Name] for Name in allNames))
print(list(combinations))

这将打印:

[('D', 'F', 'I'), ('D', 'F', 'J'), ('D', 'G', 'I'), ('D', 'G', 'J'), ('D', 'H', 'I'), ('D', 'H', 'J'), ('E', 'F', 'I'), ('E', 'F', 'J'), ('E', 'G', 'I'), ('E', 'G', 'J'), ('E', 'H', 'I'), ('E', 'H', 'J')]

需要先对字典进行排序,否则值可能会与错误的键相关联。 - spacycookie

14

ParameterGrid 是 scikit-learn 中创建生成器的方法。每个 for 循环迭代都会返回一个包含当前参数组合的字典。

from sklearn.model_selection import ParameterGrid

params = {'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
param_grid = ParameterGrid(params)
for dict_ in param_grid:
    print(dict_)
    

# output
{'A': 'D', 'B': 'F', 'C': 'I'}
...

如果您已经在使用 scikit-learn 的环境中工作,那么这很方便。不过,itertools 是标准库的一部分。 - Niko Pasanen
1
这是我情况下最好的答案,谢谢。 - Orhan Abar

1
作为补充,这里有一个使用纯Python实现的3行代码片段,让你了解其原理,但itertools确实更有效率。
res = [[]]
for _, vals in my_dict.items():
    res = [x+[y] for x in res for y in vals]
print(res)

1
from itertools import combinations

a=['I1','I2','I3','I4','I5']

list(combinations(a,2))

输出结果将为:

[('I1', 'I2'),
 ('I1', 'I3'),
 ('I1', 'I4'),
 ('I1', 'I5'),
 ('I2', 'I3'),
 ('I2', 'I4'),
 ('I2', 'I5'),
 ('I3', 'I4'),
 ('I3', 'I5'),
 ('I4', 'I5')]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接