简体   繁体   中英

Split python dictionary to result in all combinations of values

my_dict = {'a':[1,2], 'b':[3], 'c':{'d':[4,5], 'e':[6,7]}}

I need to derive all the combinations out of it as below.

{'a':1, 'b':3, 'c':{'d':4, 'e':6}}
{'a':1, 'b':3, 'c':{'d':4, 'e':7}}
{'a':1, 'b':3, 'c':{'d':5, 'e':6}}
{'a':1, 'b':3, 'c':{'d':5, 'e':7}}
{'a':2, 'b':3, 'c':{'d':4, 'e':6}}

and so on. There could be any level of nesting here
Please let me know how to achieve this
Something that I tried is pasted below but definitely was reaching nowhere

def gen_combinations(data):
    my_list =[]
    if isinstance(data, dict):
        for k, v in data.iteritems():
            if isinstance(v, dict):
                gen_combinations(v)
            elif isinstance(v, list):
                for i in range(len(v)):
                    temp_dict = data.copy()
                    temp_dict[k] = v[i]
                    print temp_dict

my_dict = {'a':[1,2], 'b':[3], 'c':{'d':[4,5], 'e':[6,7]}}

gen_combinations(my_dict)

Which resulted in

{'a': 1, 'c': {'e': [6, 7], 'd': [4, 5]}, 'b': [3]}
{'a': 2, 'c': {'e': [6, 7], 'd': [4, 5]}, 'b': [3]}
{'e': 6, 'd': [4, 5]}
{'e': 7, 'd': [4, 5]}
{'e': [6, 7], 'd': 4}
{'e': [6, 7], 'd': 5}
{'a': [1, 2], 'c': {'e': [6, 7], 'd': [4, 5]}, 'b': 3}
from itertools import product


my_dict = {'a':[1,2], 'b':[3], 'c':{'d':[4,5], 'e':[6,7]}}


def process(d):
    to_product = []  # [[('a', 1), ('a', 2)], [('b', 3),], ...]
    for k, v in d.items():
        if isinstance(v, list):
            to_product.append([(k, i) for i in v])
        elif isinstance(v, dict):
            to_product.append([(k, i) for i in process(v)])
        else:
            to_product.append([(k, v)])
    return [dict(l) for l in product(*to_product)]

for i in process(my_dict):
    print(i)

Output:

{'a': 1, 'b': 3, 'c': {'e': 6, 'd': 4}}
{'a': 2, 'b': 3, 'c': {'e': 6, 'd': 4}}
{'a': 1, 'b': 3, 'c': {'e': 6, 'd': 5}}
{'a': 2, 'b': 3, 'c': {'e': 6, 'd': 5}}
{'a': 1, 'b': 3, 'c': {'e': 7, 'd': 4}}
{'a': 2, 'b': 3, 'c': {'e': 7, 'd': 4}}
{'a': 1, 'b': 3, 'c': {'e': 7, 'd': 5}}
{'a': 2, 'b': 3, 'c': {'e': 7, 'd': 5}}

Upd:

Code that works as asked here :

from itertools import product


my_dict = {'a':[1,2], 'e':[7], 'f':{'x':[{'a':[3,5]}, {'a':[4]}] } }

def process(d):
    to_product = []  # [[('a', 1), ('a', 2)], [('b', 3),], ...]
    for k, v in d.items():
        if isinstance(v, list) and all(isinstance(i, dict) for i in v):
            # specific case, when list of dicts process differently...
            c = product(*list(process(i) for i in v))
            to_product.append([(k, list(l)) for l in c])
        elif isinstance(v, list):
            to_product.append([(k, i) for i in v])
        elif isinstance(v, dict):
            to_product.append([(k, i) for i in process(v)])
        else:
            to_product.append([(k, v)])
    return [dict(l) for l in product(*to_product)]

for i in process(my_dict):
    print(i)

Output:

{'f': {'x': [{'a': 3}, {'a': 4}]}, 'a': 1, 'e': 7}
{'f': {'x': [{'a': 3}, {'a': 4}]}, 'a': 2, 'e': 7}
{'f': {'x': [{'a': 5}, {'a': 4}]}, 'a': 1, 'e': 7}
{'f': {'x': [{'a': 5}, {'a': 4}]}, 'a': 2, 'e': 7}

Solve it with two steps.

First replace each dict with a list of dicts generated by gen_combinations, called recursively.

Second, make the inner join between all keys. Each key has a flat list now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM