![](/img/trans.png)
[英]Python using combinations to sum values in a tuple in a list in a dictionary?
[英]Combinations from dictionary with list values using Python
我有以下传入价值:
variants = {
"debug" : ["on", "off"],
"locale" : ["de_DE", "en_US", "fr_FR"],
...
}
我想处理它们,所以我得到以下结果:
combinations = [
[{"debug":"on"},{"locale":"de_DE"}],
[{"debug":"on"},{"locale":"en_US"}],
[{"debug":"on"},{"locale":"fr_FR"}],
[{"debug":"off"},{"locale":"de_DE"}],
[{"debug":"off"},{"locale":"en_US"}],
[{"debug":"off"},{"locale":"fr_FR"}]
]
这应该适用于字典中任意长度的键。 在Python中使用itertools,但没有找到符合这些要求的任何内容。
import itertools as it
varNames = sorted(variants)
combinations = [dict(zip(varNames, prod)) for prod in it.product(*(variants[varName] for varName in varNames))]
嗯,这回来了:
[{'debug': 'on', 'locale': 'de_DE'},
{'debug': 'on', 'locale': 'en_US'},
{'debug': 'on', 'locale': 'fr_FR'},
{'debug': 'off', 'locale': 'de_DE'},
{'debug': 'off', 'locale': 'en_US'},
{'debug': 'off', 'locale': 'fr_FR'}]
这可能不完全是你想要的。 让我改编一下......
combinations = [ [ {varName: val} for varName, val in zip(varNames, prod) ] for prod in it.product(*(variants[varName] for varName in varNames))]
现在返回:
[[{'debug': 'on'}, {'locale': 'de_DE'}],
[{'debug': 'on'}, {'locale': 'en_US'}],
[{'debug': 'on'}, {'locale': 'fr_FR'}],
[{'debug': 'off'}, {'locale': 'de_DE'}],
[{'debug': 'off'}, {'locale': 'en_US'}],
[{'debug': 'off'}, {'locale': 'fr_FR'}]]
Voilà;-)
combinations = [[{key: value} for (key, value) in zip(variants, values)]
for values in itertools.product(*variants.values())]
[[{'debug': 'on'}, {'locale': 'de_DE'}],
[{'debug': 'on'}, {'locale': 'en_US'}],
[{'debug': 'on'}, {'locale': 'fr_FR'}],
[{'debug': 'off'}, {'locale': 'de_DE'}],
[{'debug': 'off'}, {'locale': 'en_US'}],
[{'debug': 'off'}, {'locale': 'fr_FR'}]]
这是我使用的:
from itertools import product
def dictproduct(dct):
for t in product(*dct.itervalues()):
yield dict(zip(dct.iterkeys(), t))
适用于您的示例的内容给出:
>>> list(dictproduct({"debug":["on", "off"], "locale":["de_DE", "en_US", "fr_FR"]}))
[{'debug': 'on', 'locale': 'de_DE'},
{'debug': 'on', 'locale': 'en_US'},
{'debug': 'on', 'locale': 'fr_FR'},
{'debug': 'off', 'locale': 'de_DE'},
{'debug': 'off', 'locale': 'en_US'},
{'debug': 'off', 'locale': 'fr_FR'}]
我发现这比上面的一个衬里更具可读性。
此外,它返回一个像itertools.product
这样的迭代器,因此无论是实例化列表还是只消耗一个值,它都会让用户知道它。
我假设你想要所有键的笛卡尔积? 所以如果你有另一个条目“foo”,值为[1,2,3],那么你总共有18个条目?
首先,将值放在列表中,其中每个条目是该点中可能的变体之一。 在您的情况下,我们希望:
[[{'debug': 'on'}, {'debug': 'off'}], [{'locale': 'de_DE'}, {'locale': 'en_US'}, {'locale': 'fr_FR'}]]
要做到这一点:
>>> stuff = []
>>> for k,v in variants.items():
blah = []
for i in v:
blah.append({k:i})
stuff.append(blah)
>>> stuff
[[{'debug': 'on'}, {'debug': 'off'}], [{'locale': 'de_DE'}, {'locale': 'en_US'}, {'locale': 'fr_FR'}]]
接下来我们可以使用笛卡尔积函数来扩展它...
>>> def cartesian_product(lists, previous_elements = []):
if len(lists) == 1:
for elem in lists[0]:
yield previous_elements + [elem, ]
else:
for elem in lists[0]:
for x in cartesian_product(lists[1:], previous_elements + [elem, ]):
yield x
>>> list(cartesian_product(stuff))
[[{'debug': 'on'}, {'locale': 'de_DE'}], [{'debug': 'on'}, {'locale': 'en_US'}], [{'debug': 'on'}, {'locale': 'fr_FR'}], [{'debug': 'off'}, {'locale': 'de_DE'}], [{'debug': 'off'}, {'locale': 'en_US'}], [{'debug': 'off'}, {'locale': 'fr_FR'}]]
请注意,这不会复制dicts,因此所有{'debug': 'on'}
dicts都是相同的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.