Декартово произведение словаря списков - с сортировкой - PullRequest
0 голосов
/ 01 марта 2019

Фон

В настоящее время я использую технику , которая отлично продемонстрирована в другом посте Stackoverflow , чтобы создать декартово произведение словаря списков, то есть:

from itertools import product
def my_product(inp):
    return (dict(zip(inp.keys(), values)) for values in product(*inp.values())

Проблема

Вот мой пример словаря, d:

d = {
    "letters": ['a', 'b'],
    "numbers": [1, 2, 3],
    "status": ["on", "off"]
}

Проблема, с которой я сталкиваюсь, заключается в том, что я хочу использовать эту технику для созданиягенератор.Тем не менее, я хочу контролировать порядок, в котором «списываются» определенные списки.Например, вот общий результат для первых нескольких итераций, сгенерированных моим кодом:

{"status": "on",  "numbers": 1, "letters": 'a'}
{"status": "off", "numbers": 1, "letters": 'a'}
{"status": "on",  "numbers": 2, "letters": 'a'}
{"status": "off", "numbers": 2, "letters": 'a'}
{"status": "on",  "numbers": 3, "letters": 'a'}
{"status": "off", "numbers": 3, "letters": 'a'}
{"status": "on",  "numbers": 1, "letters": 'b'}
{"status": "off", "numbers": 1, "letters": 'b'}

Однако мне нужно иметь возможность контролировать порядок, в котором продукт генерирует эти перестановки.Код, который «подпитывает» словари, имеет высокую «стоимость», когда я переключаю значение «вкл. / Выкл.» В «статус», но штраф за изменение элементов «цифры» или «буквы» не налагается.Например, это будет идеальный набор итераций, полученных генератором:

{"letters": 'a', "numbers": 1, "status": "on"}
{"letters": 'a', "numbers": 2, "status": "on"}
{"letters": 'a', "numbers": 3, "status": "on"}
{"letters": 'b', "numbers": 1, "status": "on"}
{"letters": 'b', "numbers": 2, "status": "on"}
{"letters": 'b', "numbers": 3, "status": "on"}
{"letters": 'a', "numbers": 1, "status": "off"}
{"letters": 'a', "numbers": 2, "status": "off"}
{"letters": 'a', "numbers": 3, "status": "off"}
{"letters": 'b', "numbers": 1, "status": "off"}
{"letters": 'b', "numbers": 2, "status": "off"}
{"letters": 'b', "numbers": 3, "status": "off"}

Короче говоря, я хочу иметь возможность минимизировать количество переходов от одного значения к другому, показывая "«предпочтение» некоторым членам словаря, d.


Вопрос

Как мне это сделать?


Заключение

Используя принятый ответ, я сгенерировал этот фрагмент кода:


Список кодов

#!/usr/bin/env python
from collections import OrderedDict
from itertools import product

d = OrderedDict()
d["status"] = ["on", "off"]
d["letters"] = ["a", "b", "c"]
d["numbers"] = [1, 2, 3, 4]

for i in (dict(zip(inp.keys(), values)) for values in product(*inp.values())):
    print(i)

Пример вывода

{'status': 'on', 'letters': 'a', 'numbers': 1}
{'status': 'on', 'letters': 'a', 'numbers': 2}
{'status': 'on', 'letters': 'a', 'numbers': 3}
{'status': 'on', 'letters': 'a', 'numbers': 4}
{'status': 'on', 'letters': 'b', 'numbers': 1}
{'status': 'on', 'letters': 'b', 'numbers': 2}
{'status': 'on', 'letters': 'b', 'numbers': 3}
{'status': 'on', 'letters': 'b', 'numbers': 4}
{'status': 'on', 'letters': 'c', 'numbers': 1}
{'status': 'on', 'letters': 'c', 'numbers': 2}
{'status': 'on', 'letters': 'c', 'numbers': 3}
{'status': 'on', 'letters': 'c', 'numbers': 4}
{'status': 'off', 'letters': 'a', 'numbers': 1}
{'status': 'off', 'letters': 'a', 'numbers': 2}
{'status': 'off', 'letters': 'a', 'numbers': 3}
{'status': 'off', 'letters': 'a', 'numbers': 4}
{'status': 'off', 'letters': 'b', 'numbers': 1}
{'status': 'off', 'letters': 'b', 'numbers': 2}
{'status': 'off', 'letters': 'b', 'numbers': 3}
{'status': 'off', 'letters': 'b', 'numbers': 4}
{'status': 'off', 'letters': 'c', 'numbers': 1}
{'status': 'off', 'letters': 'c', 'numbers': 2}
{'status': 'off', 'letters': 'c', 'numbers': 3}
{'status': 'off', 'letters': 'c', 'numbers': 4}

1 Ответ

0 голосов
/ 01 марта 2019

Если вы используете Python 3.5 или более позднюю версию, вместо этого вы можете сделать status первым ключом в вашем dict:

d = {
    "status": ["on", "off"],
    "letters": ['a', 'b'],
    "numbers": [1, 2, 3]
}

Для более ранних версий используйте collections.OrderedDict вместо dict.

...