Python3 itertools.permutations по списку списков? - PullRequest
0 голосов
/ 25 апреля 2019

Скажите, у меня есть список списков. Каждый ключ представляет переменную, а каждый список представляет возможные значения, которые может иметь переменная.

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

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

Теперь, как мне получить список диктов для всех перестановок aBool, bInt и cFloat? Каждая запись в списке будет диктовать. Каждый 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 },
]

Ответы [ 2 ]

0 голосов
/ 25 апреля 2019

На самом деле, вы не хотите перестановок. Вы хотите декартово произведение.

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}]
0 голосов
/ 25 апреля 2019

Было бы быстрее, если бы вы сначала не поместили его в 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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...