[英]How can I calculate all combinations of N different dictionaries in Python
The Challenge挑战
I need to combine various dictionaries together to obtain all possible combinations, whilst also having an approach that can take (N) number of dictionaries.我需要将各种词典组合在一起以获得所有可能的组合,同时还需要一种可以采用 (N) 个词典的方法。 I have the following code which works for a single case, but I'm seeking a more elegant and scalable solution.
我有以下适用于单个案例的代码,但我正在寻找更优雅和可扩展的解决方案。
Current Solution当前解决方案
This works for a specified number of dictionaries (profile, env, test_vars):这适用于指定数量的字典(配置文件、环境、test_vars):
profile = {
"normal": {"profile": "normal"},
"special": {"profile": "special"}
}
environment = {
"legacy": {"id": 123},
"staging": {"id": 123, "sid": 123123},
"production": {"pid": 14941729}
}
test_vars = {
"no_tests": {"var1": ""},
"var1:prod": {"var1": "prod"},
"var1+var2": {"var1": "alpha", "var2": "alpha"},
"var2_beta": {"var2": "beta"},
"var2_alpha": {"var2": "alpha"}
}
total = [
{"{}|{}|{}".format(pk, ek, tk): {**pv, **ev, **tv}}
for pk, pv in profile.items()
for ek, ev in environment.items()
for tk, tv in test_vars.items()
]
result = [{id: '&'.join(["{}={}".format(i, x) for i, x in v.items()])
for id, v in condition.items()}
for condition in total]
result
Result :结果:
The output looks like this, where each element of the list specifies a "test identifier" and the "test variables" expressed as querystring parameters. output 看起来像这样,其中列表的每个元素指定一个“测试标识符”和表示为查询字符串参数的“测试变量”。
Out[68]:
[{'normal|legacy|no_tests': 'profile=normal&id=123&var1='},
{'normal|legacy|var1:prod': 'profile=normal&id=123&var1=prod'},
{'normal|legacy|var1+var2': 'profile=normal&id=123&var1=alpha&var2=alpha'},
{'normal|legacy|var2_beta': 'profile=normal&id=123&var2=beta'},
{'normal|legacy|var2_alpha': 'profile=normal&id=123&var2=alpha'},
{'normal|staging|no_tests': 'profile=normal&id=123&sid=123123&var1='},
{'normal|staging|var1:prod': 'profile=normal&id=123&sid=123123&var1=prod'},
{'normal|staging|var1+var2': 'profile=normal&id=123&sid=123123&var1=alpha&var2=alpha'},
{'normal|staging|var2_beta': 'profile=normal&id=123&sid=123123&var2=beta'},
{'normal|staging|var2_alpha': 'profile=normal&id=123&sid=123123&var2=alpha'},
{'normal|production|no_tests': 'profile=normal&pid=14941729&var1='},
{'normal|production|var1:prod': 'profile=normal&pid=14941729&var1=prod'},
{'normal|production|var1+var2': 'profile=normal&pid=14941729&var1=alpha&var2=alpha'},
{'normal|production|var2_beta': 'profile=normal&pid=14941729&var2=beta'},
{'normal|production|var2_alpha': 'profile=normal&pid=14941729&var2=alpha'},...
My issue我的问题
This isn't scalable to adding several more configuration dictionaries.这不能扩展到添加更多的配置字典。
Let's say I now wanted to add another configuration dictionary, say, release
.假设我现在想添加另一个配置字典,比如
release
。 I'd have to add that new dict, plus amend the "total" comprehension like thus:我必须添加那个新的字典,并像这样修改“总”理解:
total = [
{"{}|{}|{}|{}".format(pk, ek, tk, rk): {**pv, **ev, **tv, **rv}}
for pk, pv in profile.items()
for ek, ev in environment.items()
for tk, tv in test_vars.items()
for rk, rv in release_vars.items()
]
Which seems inelegant, especially when I could be dealing with 00's of configuration dictionaries.这似乎不够优雅,尤其是当我可以处理 00 的配置字典时。
Can anyone help devise something more scalable?任何人都可以帮助 devise 一些更具可扩展性的东西吗?
you could try something like this:你可以尝试这样的事情:
from itertools import product
def t(*args):
counter = len(args)
tmp = [i.keys() for i in args]
s = {"|".join(i): [l[k] for l,k in zip(args,i)] for i in product(*tmp)}
for k, v in s.items():
s[k] = "&".join(["%s=%s"%(v1,v2) for j in v for v1,v2 in j.items()])
return s
from pprint import pprint
pprint(t(profile, environment, test_vars))
Result:结果:
{'normal|legacy|no_tests': 'profile=normal&id=123&var1=',
'normal|legacy|var1+var2': 'profile=normal&id=123&var1=alpha&var2=alpha',
'normal|legacy|var1:prod': 'profile=normal&id=123&var1=prod',
'normal|legacy|var2_alpha': 'profile=normal&id=123&var2=alpha', ...
PS This is not necessary the best solution, but it could be scaled, good luck:) PS 这不是最好的解决方案,但它可以扩展,祝你好运:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.