2016-03-24 17 views
7
my_dict = {'a':[1,2], 'b':[3], 'c':{'d':[4,5], 'e':[6,7]}} 

Ho bisogno di derivarne tutte le combinazioni come di seguito.Dizionario Python diviso per ottenere tutte le combinazioni di valori

{'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}} 

e così via. Ci potrebbe essere qualsiasi livello di nidificazione qui
prega fatemi sapere come raggiungere questo obiettivo
Qualcosa che ho provato è incollato al di sotto, ma sicuramente è stato raggiunto da nessuna parte

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) 

che ha provocato

{'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} 
+1

Per favore, facci sapere cosa hai provato finora! –

+0

Suppongo che vogliate appiattire anche le diciture annidate? –

+0

@Suren puoi guardare la discussione sotto la mia risposta? Quale output per la chiave 'e' vuoi per' {'a': [1, 2], 'b': [3], 'c': {'d': {4: [3, 4]}, 'e': [6, 7, [1, 2]]}} '? –

risposta

9
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) 

Uscita:

{'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:

codice che funziona come chiesto 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) 

uscita:

{'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} 
+0

Ottima risposta, non sapeva prima della funzione 'prodotto', molto utile! –

+0

Bello! Che ne dici di consentire qualsiasi altro iterabile tranne il semplice filtro per la lista? Nelle righe di 'try: to_product.append ([{k: i} per i in v]) tranne TypeError: ...'? – hochl

+0

Penso che questo fallirà per le diciture annidate '{'a': [1, 2], 'b': [3], 'c': {'d': {4: [3, 4]}, 'e ': [6, 7, [1, 2]]}} ' –

-1

risolverlo con due passaggi.

Sostituire innanzitutto ogni dict con un elenco di dts generato da gen_combinations, chiamato in modo ricorsivo.

In secondo luogo, effettuare l'unione interna tra tutte le chiavi. Ogni chiave ha ora una lista piatta.