У меня есть словарь списков. Я хочу сгенерировать все комбинации этих списков и вернуть эти комбинации в виде списка словарей с правильными сопоставлениями ключей и пар значений.

До сих пор я добился этого, развернув приведенный ниже код, но я хочу быть явным в отношении отображений пар ключ-значение на протяжении всего процесса, а не полагаться на подход перечисления ниже. Я обеспокоен, учитывая, что словарь не упорядочен, чтобы подход перечисления мог быть открыт для неправильного отображения пар ключ-значение. В любом случае, я ищу самый питонический способ достижения результата.

import itertools

dct_lst = {'Apple':[3,5,7],'Pear':[5,2],'Orange':[10],'Banana':[7,10],'Lemon':[5,7,9,2,1]}

combs = itertools.product(*(dct_lst[key] for key in dct_lst.keys()))

lst_dct = []
for comb in combs:
    dct = {}
    for j,key in enumerate(dct_lst.keys()):
        dct[key] = comb[j]
    lst_dct.append(dct)

lst_dct

[{'Apple': 3, 'Banana': 7, 'Lemon': 5, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 7, 'Lemon': 7, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 7, 'Lemon': 9, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 7, 'Lemon': 2, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 7, 'Lemon': 1, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 10, 'Lemon': 5, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 10, 'Lemon': 7, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 10, 'Lemon': 9, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 10, 'Lemon': 2, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 10, 'Lemon': 1, 'Orange': 10, 'Pear': 5},
 {'Apple': 3, 'Banana': 7, 'Lemon': 5, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 7, 'Lemon': 7, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 7, 'Lemon': 9, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 7, 'Lemon': 2, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 7, 'Lemon': 1, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 10, 'Lemon': 5, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 10, 'Lemon': 7, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 10, 'Lemon': 9, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 10, 'Lemon': 2, 'Orange': 10, 'Pear': 2},
 {'Apple': 3, 'Banana': 10, 'Lemon': 1, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 7, 'Lemon': 5, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 7, 'Lemon': 7, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 7, 'Lemon': 9, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 7, 'Lemon': 2, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 7, 'Lemon': 1, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 10, 'Lemon': 5, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 10, 'Lemon': 7, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 10, 'Lemon': 9, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 10, 'Lemon': 2, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 10, 'Lemon': 1, 'Orange': 10, 'Pear': 5},
 {'Apple': 5, 'Banana': 7, 'Lemon': 5, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 7, 'Lemon': 7, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 7, 'Lemon': 9, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 7, 'Lemon': 2, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 7, 'Lemon': 1, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 10, 'Lemon': 5, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 10, 'Lemon': 7, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 10, 'Lemon': 9, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 10, 'Lemon': 2, 'Orange': 10, 'Pear': 2},
 {'Apple': 5, 'Banana': 10, 'Lemon': 1, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 7, 'Lemon': 5, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 7, 'Lemon': 7, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 7, 'Lemon': 9, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 7, 'Lemon': 2, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 7, 'Lemon': 1, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 10, 'Lemon': 5, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 10, 'Lemon': 7, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 10, 'Lemon': 9, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 10, 'Lemon': 2, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 10, 'Lemon': 1, 'Orange': 10, 'Pear': 5},
 {'Apple': 7, 'Banana': 7, 'Lemon': 5, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 7, 'Lemon': 7, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 7, 'Lemon': 9, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 7, 'Lemon': 2, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 7, 'Lemon': 1, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 10, 'Lemon': 5, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 10, 'Lemon': 7, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 10, 'Lemon': 9, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 10, 'Lemon': 2, 'Orange': 10, 'Pear': 2},
 {'Apple': 7, 'Banana': 10, 'Lemon': 1, 'Orange': 10, 'Pear': 2}]

Результат, как и ожидалось. Тем не менее, я заинтересован в наиболее надежном питоническом способе достижения этого результата.

1
agftrading 9 Июл 2019 в 20:47

3 ответа

Лучший ответ

Вы можете использовать itertools.product только для значений dict, а затем dict(zip(...)) ключи и значения вместе для вывода списка dict.

from itertools import product

d = {'Apple':[3,5,7],'Pear':[5,2],'Orange':[10],'Banana':[7,10],'Lemon':[5,7,9,2,1]}

l = [dict(zip(d.keys(), vals)) for vals in product(*d.values())]
print(l)
# [{'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 9}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 2}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 1}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 5}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 7}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 9}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 2}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 1}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 9}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 2}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 1}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 5}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 7}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 9}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 2}, {'Apple': 3, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 1}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 9}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 2}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 1}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 5}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 7}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 9}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 2}, {'Apple': 5, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 1}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 9}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 2}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 1}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 5}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 7}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 9}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 2}, {'Apple': 5, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 1}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 9}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 2}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 1}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 5}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 7}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 9}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 2}, {'Apple': 7, 'Pear': 5, 'Orange': 10, 'Banana': 10, 'Lemon': 1}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 9}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 2}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 7, 'Lemon': 1}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 5}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 7}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 9}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 2}, {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 1}]
1
benvc 9 Июл 2019 в 20:59

Вы можете повторить ключ вместе со значениями, чтобы создать список элементов:

>>> import itertools
>>> dct_lst = {'Apple':[3,5,7],'Pear':[5,2],'Orange':[10],'Banana':[7,10],'Lemon':[5,7,9,2,1]}
>>> L = [[(k, v) for v in vs] for k, vs in dct_lst.items()]
>>> L
[[('Apple', 3), ('Apple', 5), ('Apple', 7)], [('Pear', 5), ('Pear', 2)], [('Orange', 10)], [('Banana', 7), ('Banana', 10)], [('Lemon', 5), ('Lemon', 7), ('Lemon', 9), ('Lemon', 2), ('Lemon', 1)]]

И используйте itertools.product для создания всех комбинаций:

>>> list (itertools.product(*L))
[(('Apple', 3), ('Pear', 5), ('Orange', 10), ('Banana', 7), ('Lemon', 5)), (('Apple', 3), ('Pear', 5), ('Orange', 10), ('Banana', 7), ('Lemon', 7)), (('Apple', 3), ('Pear', 5), ('Orange', 10), ('Banana', 7), ('Lemon', 9)), ..., (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 7), ('Lemon', 2)), (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 7), ('Lemon', 1)), (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 10), ('Lemon', 5)), (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 10), ('Lemon', 7)), (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 10), ('Lemon', 9)), (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 10), ('Lemon', 2)), (('Apple', 7), ('Pear', 2), ('Orange', 10), ('Banana', 10), ('Lemon', 1))]

Выходные данные состоят из кортежей, но их легко создавать:

>>> list(map(dict, itertools.product(*L)))
[{'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 5}, {'Apple': 3, 'Pear': 5, 'Orange': 10, 'Banana': 7, 'Lemon': 7}, ..., {'Apple': 7, 'Pear': 2, 'Orange': 10, 'Banana': 10, 'Lemon': 1}]
2
jferard 9 Июл 2019 в 20:38

Вы можете использовать ChianMap, чтобы помочь объединить дикты в конце.

Попробуй это:

from itertools import product
from collections import ChainMap

dct_lst = {'Apple':[3,5,7],'Pear':[5,2],'Orange':[10],'Banana':[7,10],'Lemon':[5,7,9,2,1]}

flat_dicts = [[{key: val} for val in lst] for key, lst in dct_lst.items()]
lst_dct = list(map(lambda d: dict(ChainMap(*d)), product(*flat_dicts)))

print(lst_dct)
1
Adam.Er8 9 Июл 2019 в 18:17