说我有一个列表的字典。每个键代表一个变量,每个列表代表变量可以具有的值。
myBools = [ True, False ]
myInts = [ -3, 0, 4 ]
myFloats = [ -2.2, 0.0, 1.1 ]
myDict = {
'aBool': myBools,
'bInt': myInts,
'cFloat': myFloats,
}
现在,我如何获得aBool,bInt和cFloat的所有排列的dicts列表?每个列表条目都是一个词典。每个dict都有一组唯一的值代表一个排列。
预期:
myPermList = [
{ 'aBool': True, 'bInt': -3, 'cFloat': -2.2 },
{ 'aBool': True, 'bInt': -3, 'cFloat': 0.0 },
{ 'aBool': True, 'bInt': -3, 'cFloat': 1.1 },
# ...
{ 'aBool': False, 'bInt': 4, 'cFloat': -2.2 },
{ 'aBool': False, 'bInt': 4, 'cFloat': 0.0 },
{ 'aBool': False, 'bInt': 4, 'cFloat': 1.1 },
]
我无法弄清楚itertools.permutations是否可以帮助我,如果是这样,如何设置调用。
这种技术的预期用途是帮助以全面和系统的方式自动测试一些其他功能,以便我可以扩展列表以包括好的和坏的数据,以便在良好数据和正确错误的情况下测试正确的功能。处理坏数据的情况。
myBools,myInts和myFloats将代表可以重用的各种数据类型的测试。这些可以在将来混合使用(即测试int和float数据)。但是所写的代码代表了我能想到的最简单,最通用的输入和输出数据结构。
编辑注1:
我发现我最初安排问题的方式存在限制,这种限制不允许我想要的自动化水平。可重用集的初始定义将集名称保留为变量。但是,这可能是将来相关的元数据,如果存储为字典键而不是尝试使用代码分析或元编程技术进行提取,则更容易访问。
随后,我为myDict选择了一个更具描述性的名称,例如: myOptions。然后,我使用其他集和选项更明确地演示了意图。现在,如果我希望用额外的代码分析选项,那就容易多了。这并没有真正改变初始问题,只是包含更多操作来设置将被利用的itertools函数(产品或置换)。
最后,由于我显然不是在寻找排列而是笛卡尔积(感谢校正!),我将存储结果更准确,更简单地命名为myOptsList。
mySets = {
'myBools1': [ True, False ],
'myInts1': [ -3, 0, 4 ],
'myFloats1': [ -2.2, 0.0, 1.1 ],
'myInts2': [ -500, -250, 0, 250, 500 ],
'myFloats2': [ -88.8, -44.4, -0.0, +0.0, 44.4, 88.8 ],
# ... arbitrary number of sets
}
myOptions = {
'aBool': mySets[ 'myBools1' ],
'bInt': mySets[ 'myInts1' ],
'cFloat': mySets[ 'myFloats1' ],
'dInt': mySets[ 'myInts1' ],
'eInt': mySets[ 'myInts2' ],
'fInt': mySets[ 'myInts1' ],
'gFloat': mySets[ 'myFloats2' ],
# ... arbitary number of options,
# potentially reusing sets
}
# Set up parameters and find Cartesian product
myOptsList = [
{ 'aBool': True, 'bInt': -3, 'cFloat': -2.2, 'dInt': -3, 'eInt': -500, 'fInt': -3, 'gFloat': -88.8 },
# ...
{ 'aBool': False, 'bInt': 4, 'cFloat': 1.1, 'dInt': 4, 'eInt': 500, 'fInt': 4, 'gFloat': 88.8 },
]
实际上,你不需要排列。你想要笛卡尔产品。
from itertools import product
myPermList = [{'aBool':c[0],'bInt':c[1],'cFloat':c[2]} for c in list(product(myBools,myInts,myFloats))]
输出:
[{'aBool': True, 'bInt': -3, 'cFloat': -2.2},
{'aBool': True, 'bInt': -3, 'cFloat': 0.0},
{'aBool': True, 'bInt': -3, 'cFloat': 1.1},
{'aBool': True, 'bInt': 0, 'cFloat': -2.2},
{'aBool': True, 'bInt': 0, 'cFloat': 0.0},
{'aBool': True, 'bInt': 0, 'cFloat': 1.1},
{'aBool': True, 'bInt': 4, 'cFloat': -2.2},
{'aBool': True, 'bInt': 4, 'cFloat': 0.0},
{'aBool': True, 'bInt': 4, 'cFloat': 1.1},
{'aBool': False, 'bInt': -3, 'cFloat': -2.2},
{'aBool': False, 'bInt': -3, 'cFloat': 0.0},
{'aBool': False, 'bInt': -3, 'cFloat': 1.1},
{'aBool': False, 'bInt': 0, 'cFloat': -2.2},
{'aBool': False, 'bInt': 0, 'cFloat': 0.0},
{'aBool': False, 'bInt': 0, 'cFloat': 1.1},
{'aBool': False, 'bInt': 4, 'cFloat': -2.2},
{'aBool': False, 'bInt': 4, 'cFloat': 0.0},
{'aBool': False, 'bInt': 4, 'cFloat': 1.1}]
如果你没先把它放在dict
中会更快但这个解决方案有效。这也是动态的,如果您向dict添加条目和列表,解决方案仍将按预期工作。
from itertools import product # This will get all permutations
myBools = [ True, False ]
myInts = [ -3, 0, 4 ]
myFloats = [ -2.2, 0.0, 1.1 ]
myDict = {
'aBool': myBools,
'bInt': myInts,
'cFloat': myFloats,
}
# First we need to grab the keys and values
keys, vals = list(myDict.keys()), list(myDict.values())
# Then we find all permutations for those values
permutations = list(product(*vals))
# Finally we can create out list of dicts
result = [{keys[index]: entry[index] for index in range(len(entry))} for entry in permutations]
# You combine the above to statements into a single list comprehension
# if you want but I though this way was more readable.
for x in result:
print(x)
输出:
{'aBool': True, 'bInt': -3, 'cFloat': -2.2}
{'aBool': True, 'bInt': -3, 'cFloat': 0.0}
{'aBool': True, 'bInt': -3, 'cFloat': 1.1}
{'aBool': True, 'bInt': 0, 'cFloat': -2.2}
{'aBool': True, 'bInt': 0, 'cFloat': 0.0}
{'aBool': True, 'bInt': 0, 'cFloat': 1.1}
{'aBool': True, 'bInt': 4, 'cFloat': -2.2}
{'aBool': True, 'bInt': 4, 'cFloat': 0.0}
{'aBool': True, 'bInt': 4, 'cFloat': 1.1}
{'aBool': False, 'bInt': -3, 'cFloat': -2.2}
{'aBool': False, 'bInt': -3, 'cFloat': 0.0}
{'aBool': False, 'bInt': -3, 'cFloat': 1.1}
{'aBool': False, 'bInt': 0, 'cFloat': -2.2}
{'aBool': False, 'bInt': 0, 'cFloat': 0.0}
{'aBool': False, 'bInt': 0, 'cFloat': 1.1}
{'aBool': False, 'bInt': 4, 'cFloat': -2.2}
{'aBool': False, 'bInt': 4, 'cFloat': 0.0}
{'aBool': False, 'bInt': 4, 'cFloat': 1.1}