Конвертировать dict в список dict для каждой комбинации - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть запрос, похожий на этот:

my_dict = {
    "a":[1, 2, 3],
    "b":[10],
    "c":[4, 5],
    "d":[11]
}

И я хотел бы получить список, содержащий все комбинации, содержащие ключи и значение, как это:

result = [
    {"a":1, "b":10, "c":4, "d":11},
    {"a":1, "b":10, "c":5, "d":11},
    {"a":2, "b":10, "c":4, "d":11},
    {"a":2, "b":10, "c":5, "d":11},
    {"a":3, "b":10, "c":4, "d":11},
    {"a":3, "b":10, "c":5, "d":11}
]

Есть ли у кого-торешение для этого?Есть ли какое-либо существующее решение для этого или как мне поступить, чтобы сделать это самому?

Спасибо.

Ответы [ 5 ]

0 голосов
/ 22 ноября 2018

itertools.product создает комбинации из списка итераторов.

dict.values() получает необходимый список.

Для каждой комбинации zip увеличивает dict.keys() комбинацией.

Используйте list comprehension, чтобы собрать их:

from itertools import product
from pprint import pprint

my_dict = {
    "a":[1, 2, 3],
    "b":[10],
    "c":[4, 5],
    "d":[11]
}

result = [dict(zip(my_dict,i)) for i in product(*my_dict.values())]
pprint(result)

Вывод:

[{'a': 1, 'b': 10, 'c': 4, 'd': 11},
 {'a': 1, 'b': 10, 'c': 5, 'd': 11},
 {'a': 2, 'b': 10, 'c': 4, 'd': 11},
 {'a': 2, 'b': 10, 'c': 5, 'd': 11},
 {'a': 3, 'b': 10, 'c': 4, 'd': 11},
 {'a': 3, 'b': 10, 'c': 5, 'd': 11}]
0 голосов
/ 22 ноября 2018

Вы можете использовать:

from itertools import product
allNames = sorted(my_dict)
values= list(product(*(my_dict[Name] for Name in allNames)))
d = list(dict(zip(['a','b','c','d'],i)) for i in values)

Выход:

[{'a': 1, 'c': 4, 'b': 10, 'd': 11}, 
{'a': 1, 'c': 5, 'b': 10, 'd': 11}, 
{'a': 2, 'c': 4, 'b': 10, 'd': 11}, 
{'a': 2, 'c': 5, 'b': 10, 'd': 11}, 
{'a': 3, 'c': 4, 'b': 10, 'd': 11}, 
{'a': 3, 'c': 5, 'b': 10, 'd': 11}]
0 голосов
/ 22 ноября 2018

Предполагая, что вас интересует только то, что my_dict имеет 4 ключа, достаточно просто использовать вложенные циклы:

my_dict = {
    "a": [1, 2, 3],
    "b": [10],
    "c": [4, 5],
    "d": [11]
}

result = []
for a_val in my_dict['a']:
    for b_val in my_dict['b']:
        for c_val in my_dict['c']:
            for d_val in my_dict['d']:
                result.append({'a': a_val, 'b': b_val, 'c': c_val, 'd': d_val})

print(result)

Это дает ожидаемый результат.

0 голосов
/ 22 ноября 2018

Задача для itertools.product:

>>> from itertools import product
>>> for dict_items in product(*[product([k],v) for k, v in my_dict.items()]):
...    print(dict(dict_items))

{'a': 1, 'b': 10, 'c': 4, 'd': 11}
{'a': 1, 'b': 10, 'c': 5, 'd': 11}
{'a': 2, 'b': 10, 'c': 4, 'd': 11}
{'a': 2, 'b': 10, 'c': 5, 'd': 11}
{'a': 3, 'b': 10, 'c': 4, 'd': 11}
{'a': 3, 'b': 10, 'c': 5, 'd': 11}

Небольшое объяснение:

Внутренний product(...) расширит диктат до списка, такого как [[(k1, v11), (k1, v12), ...], [(k2, v21), (k2, v22), ...], ...].

Внешний product(...) соберет списки элементов, выбрав один кортеж из каждого списка.

dict(...) создаст словарь из последовательности (k1, v#), (k2, v#), ... кортежей.

0 голосов
/ 22 ноября 2018

Попробуйте:

def permute(d):
    k = d.keys()
    perms = itertools.product(*d.values())
    return [dict(zip(k, v)) for v in perms]

>>> pprint(permute(my_dict))
[{'a': 1, 'b': 10, 'c': 4, 'd': 11},
 {'a': 1, 'b': 10, 'c': 5, 'd': 11},
 {'a': 2, 'b': 10, 'c': 4, 'd': 11},
 {'a': 2, 'b': 10, 'c': 5, 'd': 11},
 {'a': 3, 'b': 10, 'c': 4, 'd': 11},
 {'a': 3, 'b': 10, 'c': 5, 'd': 11}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...