清单字典上的Python3 itertools.permutations?

时间:2019-04-25 00:56:44

标签: python-3.x list dictionary iterator permutation

说我有一个清单的字典。每个键代表一个变量,每个列表代表该变量可以具有的可能值。

myBools = [ True, False ]
myInts = [ -3, 0, 4 ]
myFloats = [ -2.2, 0.0, 1.1 ]

myDict = {
    'aBool': myBools,
    'bInt': myInts,
    'cFloat': myFloats,
}

现在,如何获取aBool,bInt和cFloat的所有排列的字典列表?每个列表条目都是一个字典。每个字典将具有一组代表一个排列的唯一值。

预期:

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 },
]

2 个答案:

答案 0 :(得分:0)

如果不先将其放在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}

答案 1 :(得分:0)

实际上,您不需要排列。您需要笛卡尔积。

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}]