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

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

Если мы дадим эту диктовку итератору ...

{
    "key0": {
        "key1": [1, 2],
        "key2": [8, 9, 10]
    }
    "key3": [22, 23, 24]
}

Первая итерация, которую он должен произвести, это ...

{
    "key0": {
        "key1": 1,
        "key2": 8
    }
    "key3": 22
}

Тогда второе это ...

{
    "key0": {
        "key1": 2,
        "key2": 8
    }
    "key3": 22
}

Тогда третье это ... (Обратите внимание, как key1 возвращается к 1)

{
    "key0": {
        "key1": 1,
        "key2": 9
    }
    "key3": 22
}

Ожидаемый результат - перебирать все возможные состояния словаря (всего 18), где список в каждом ключе определяет возможные значения для этого ключа.

1
Colman Koivisto 3 Июл 2019 в 01:19

4 ответа

Лучший ответ

Вот краткий подход с использованием itertools.product и рекурсии:

from itertools import product

def traverse(d):
    K,V = zip(*d.items())
    for v in product(*(v if isinstance(v,list) else traverse(v) for v in V)):
        yield dict(zip(K,v))

Образец прогона:

>>> d = {
>>>     "key0": {
>>>         "key1": [1, 2],
>>>         "key2": [8, 9, 10]
>>>     },
>>>     "key3": [22, 23, 24]
>>> }

>>> from pprint import pprint
>>> pprint([*traverse(d)])
[{'key0': {'key1': 1, 'key2': 8}, 'key3': 22},
 {'key0': {'key1': 1, 'key2': 8}, 'key3': 23},
 {'key0': {'key1': 1, 'key2': 8}, 'key3': 24},
 {'key0': {'key1': 1, 'key2': 9}, 'key3': 22},
 {'key0': {'key1': 1, 'key2': 9}, 'key3': 23},
 {'key0': {'key1': 1, 'key2': 9}, 'key3': 24},
 {'key0': {'key1': 1, 'key2': 10}, 'key3': 22},
 {'key0': {'key1': 1, 'key2': 10}, 'key3': 23},
 {'key0': {'key1': 1, 'key2': 10}, 'key3': 24},
 {'key0': {'key1': 2, 'key2': 8}, 'key3': 22},
 {'key0': {'key1': 2, 'key2': 8}, 'key3': 23},
 {'key0': {'key1': 2, 'key2': 8}, 'key3': 24},
 {'key0': {'key1': 2, 'key2': 9}, 'key3': 22},
 {'key0': {'key1': 2, 'key2': 9}, 'key3': 23},
 {'key0': {'key1': 2, 'key2': 9}, 'key3': 24},
 {'key0': {'key1': 2, 'key2': 10}, 'key3': 22},
 {'key0': {'key1': 2, 'key2': 10}, 'key3': 23},
 {'key0': {'key1': 2, 'key2': 10}, 'key3': 24}]
2
Paul Panzer 3 Июл 2019 в 01:49

Вот мое решение:

xdict = {
    "key0": {
        "key1": [1, 2],
        "key2": [8, 9, 10]
    },
    "key3": [22, 23, 24]
}

def iterate (key, index):
    if (type(key) == list):
        if (index >= len(key)):
            return (key[0])
        else:
            return (key[index])
    elif (type(key) == dict):
        result = {}
        for item in key:
            result[item] = iterate(key[item], index)
        return result

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

>>> iterate(xdict, 0)
{'key0': {'key1': 1, 'key2': 8}, 'key3': 22}
>>> iterate(xdict, 1)
{'key0': {'key1': 2, 'key2': 9}, 'key3': 23}
>>> iterate(xdict, 2)
{'key0': {'key1': 1, 'key2': 10}, 'key3': 24}
0
sudohumberto 2 Июл 2019 в 22:52

Словари не являются упорядоченными структурами, вам не следует пытаться их перебирать. Однако, если вы должны сделать это, подход может быть:

my_dict = {"a":1 ,"b":2,"c":3}

for key in my_dict.keys():
    #print the key
    print(key)
    #print the value corresponding to the key
    print(my_dict[key])

Замените отпечатки на любую функцию, которую вы хотите, и все будет хорошо! Если у вас есть вложенные словари или списки, имейте в виду, что значения являются (в вашем случае) словарями или списками, оттуда вы можете манипулировать ими в цикле аналогичным образом.

my_dict = {"a":{"a_1":1,"a_2":2} ,"b":{"b_1":1,"b_2":2},"c":{"b_1":1,"b_2":2}}

for key in my_dict.keys():
    #print the key
    print(key)
    #print the dictionary corresponding to the key
    print(my_dict[key])
    for new_key in my_dict[key].keys():
        #print the keys of the nested dictionaries
        print(new_key)
        #print the values of the nested dictionaries
        print(my_dict[key][new_key])

Это должно работать

0
Preto 2 Июл 2019 в 22:28

Вот моя попытка (извините, заказ еще не правильный):

from collections import OrderedDict
from itertools import product
from copy import deepcopy


input_dicts = {'key0': {'key1': [1, 2], 'key2': [8, 9, 10]}, 'key3': [22, 23, 24]}
input_list_of_list = []
od = OrderedDict()

for k, v in input_dicts.items():
    if isinstance(v, list):
        input_list_of_list.append(v)
        od[k] = None
    elif isinstance(v, dict):
        od[k] = OrderedDict()
        for k1, v1 in v.items():
            if isinstance(v1, list):
                input_list_of_list.append(v1)
                od[k][k1] = None

all_combinations = product(*input_list_of_list)
output = []
for c in all_combinations:
    l = len(c)
    s = 0
    for k, v in od.items():
        if not isinstance(v, dict):
            od[k] = c[s]
            s += 1
        else:
            for k1 in v:
                od[k][k1] = c[s]
                s += 1
    output.append(deepcopy(od))

Выход:

[
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 8)])), ("key3", 22)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 8)])), ("key3", 23)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 8)])), ("key3", 24)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 9)])), ("key3", 22)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 9)])), ("key3", 23)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 9)])), ("key3", 24)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 10)])), ("key3", 22)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 10)])), ("key3", 23)]),
    OrderedDict([("key0", OrderedDict([("key1", 1), ("key2", 10)])), ("key3", 24)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 8)])), ("key3", 22)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 8)])), ("key3", 23)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 8)])), ("key3", 24)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 9)])), ("key3", 22)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 9)])), ("key3", 23)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 9)])), ("key3", 24)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 10)])), ("key3", 22)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 10)])), ("key3", 23)]),
    OrderedDict([("key0", OrderedDict([("key1", 2), ("key2", 10)])), ("key3", 24)]),
]
0
LiuXiMin 3 Июл 2019 в 01:41