Python recursion with dicts -
Python recursion with dicts -
i beg help in order solve problem i'm losing mind since 3 days.
it's pretty hard explain i'm trying transform dict:
{ 'contrats': [ { 'code': '1234567890', 'produits': [ { 'code': 'magenta', }, { 'code': 'emeraude', }, ], 'familles': [ { 'code': 'famille_klein', 'personnes': [ { 'code': 'mr_klein', 'nom': 'klein', 'prenom': 'monsieur', 'date_naissance': '01/01/1973', 'role_famille': 'a', 'roles_contrat': ['a', 's', 'p'], }, { 'code': 'mme_klein', 'nom': 'klein', 'prenom': 'madame', 'date_naissance': '01/01/1976', 'role_famille': 'c', 'roles_contrat': ['c'], }, { 'code': 'e1_klein', 'nom': 'klein', 'prenom': 'enfant 1', 'date_naissance': '01/01/1998', 'role_famille': 'e', 'roles_contrat': ['e'], }, { 'code': 'e2_klein', 'nom': 'klein', 'prenom': 'enfant 2', 'date_naissance': '01/01/2001', 'role_famille': 'e', 'roles_contrat': ['e'], }, ], }, ], }, ], }
http://dpaste.com/2qfmsyq
into dict:
[ { 'contrat_code': '1234567890', 'produit_code': 'magenta', 'famille_code': 'famille_klein', 'personne_code': 'mr_klein', 'personne_nom': 'klein', 'personne_prenom': 'monsieur', 'personne_date_naissance': '01/01/1973', 'personne_role_famille': 'a', 'personne_roles_contrat': ['a', 's', 'p'], }, { 'contrat_code': '1234567890', 'produit_code': 'emeraude', 'famille_code': 'famille_klein', 'personne_code': 'mr_klein', 'personne_nom': 'klein', 'personne_prenom': 'monsieur', 'personne_date_naissance': '01/01/1973', 'personne_role_famille': 'a', 'personne_roles_contrat': ['a', 's', 'p'], }, { 'contrat_code': '1234567890', 'produit_code': 'magenta', 'famille_code': 'famille_klein', 'personne_code': 'mme_klein', 'personne_nom': 'klein', 'personne_prenom': 'madame', 'personne_date_naissance': '01/01/1976', 'personne_role_famille': 'c', 'personne_roles_contrat': ['c'], }, { 'contrat_code': '1234567890', 'produit_code': 'emeraude', 'famille_code': 'famille_klein', 'personne_code': 'mme_klein', 'personne_nom': 'klein', 'personne_prenom': 'madame', 'personne_date_naissance': '01/01/1976', 'personne_role_famille': 'c', 'personne_roles_contrat': ['c'], }, { 'contrat_code': '1234567890', 'produit_code': 'magenta', 'famille_code': 'famille_klein', 'personne_code': 'e1_klein', 'personne_nom': 'klein', 'personne_prenom': 'enfant 1', 'personne_date_naissance': '01/01/1998', 'personne_role_famille': 'e', 'personne_roles_contrat': ['e'], }, { 'contrat_code': '1234567890', 'produit_code': 'emeraude', 'famille_code': 'famille_klein', 'personne_code': 'e1_klein', 'personne_nom': 'klein', 'personne_prenom': 'enfant 1', 'personne_date_naissance': '01/01/1998', 'personne_role_famille': 'e', 'personne_roles_contrat': ['e'], }, { 'contrat_code': '1234567890', 'produit_code': 'magenta', 'famille_code': 'famille_klein', 'personne_code': 'e2_klein', 'personne_nom': 'klein', 'personne_prenom': 'enfant 2', 'personne_date_naissance': '01/01/2001', 'personne_role_famille': 'e', 'personne_roles_contrat': ['e'], }, { 'contrat_code': '1234567890', 'produit_code': 'emeraude', 'famille_code': 'famille_klein', 'personne_code': 'e2_klein', 'personne_nom': 'klein', 'personne_prenom': 'enfant 2', 'personne_date_naissance': '01/01/2001', 'personne_role_famille': 'e', 'personne_roles_contrat': ['e'], }, ]
http://dpaste.com/3s5k4tf
as see, need merge keys/values (context) of dict on 1 level only.
i have origin of algorithm returns 4 contexts instead of 8 expected.
def creer_contextes(contexte, sections, ctx=none, done=none): resultats = [] ctx_local = (ctx or {}).copy() vues = (done or set()).copy() sections_ = set(aplatir(sections)) section in sections_ - vues: element in contexte.get(section, []): copie = element.copy() normalisation = normaliser(copie, section[:-1], *sections_) ctx_local.update(normalisation) vues.add(section) if vues == sections_: resultats += [ctx_local.copy()] if any(s in element.keys() s in sections_): resultats += creer_contextes(copie, sections, ctx=ctx_local, done=vues) homecoming resultats def aplatir(ilist): homecoming sum(([x] if not isinstance(x, list) else aplatir(x) x in ilist), []) def normaliser(idict, clef, *excludes): homecoming {'{}_{}'.format(clef, key): value key, value in idict.items() if key not in excludes}
thank much help provided!
you utilize itertools.product()
handle adjacent lists here, recursing construction extend result dictionary go. using itertools.product()
don't have recurse on same 'level' of nesting because there multiple nested structures in given level:
from itertools import product def recursive_flatten(d, prefix=''): result = {} nested = {} # extract 'flat' keys result key, value in d.iteritems(): result_key = (prefix + '_' + key.rstrip('s')).lstrip('_') if isinstance(value, list) , value , isinstance(value[0], dict): # nested dictionaries treated recursively nested[result_key] = value go on result[result_key] = value # no nested keys? done here if not nested: yield result homecoming # produce new re-create each combination of nested structures nested_combos in product(*nested.values()): results = [result] nested_key, nested_value in zip(nested, nested_combos): # multiply results nested results results = [ dict(r, **rec_result) rec_result in recursive_flatten(nested_value, nested_key) r in results] result in results: yield result
i producing longer keys here; prefixing nested structures key parent, recursively. prefixed contrat_
, info familles
list prefixed contrat_famille_
, etc. if don't want this, utilize nested[key.rstrip('s')] = value
instead of nested[result_key] = value
in first loop in function.
however, sense not prefixing keys can lead producing conflicting keys (if there multiple contrat
keys nested structures @ different levels of tree, example).
this assume info construction @ to the lowest degree consistent; if first element of list dictionary, all elements in list dictionaries.
this produces expected output (albeit longer keys) sample:
>>> pprint import pprint >>> pprint(list(recursive_flatten(sample))) [{'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'mr_klein', 'contrat_famille_personne_date_naissance': '01/01/1973', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'monsieur', 'contrat_famille_personne_role_famille': 'a', 'contrat_famille_personne_roles_contrat': ['a', 's', 'p'], 'contrat_produit_code': 'magenta'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'mme_klein', 'contrat_famille_personne_date_naissance': '01/01/1976', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'madame', 'contrat_famille_personne_role_famille': 'c', 'contrat_famille_personne_roles_contrat': ['c'], 'contrat_produit_code': 'magenta'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'e1_klein', 'contrat_famille_personne_date_naissance': '01/01/1998', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'enfant 1', 'contrat_famille_personne_role_famille': 'e', 'contrat_famille_personne_roles_contrat': ['e'], 'contrat_produit_code': 'magenta'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'e2_klein', 'contrat_famille_personne_date_naissance': '01/01/2001', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'enfant 2', 'contrat_famille_personne_role_famille': 'e', 'contrat_famille_personne_roles_contrat': ['e'], 'contrat_produit_code': 'magenta'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'mr_klein', 'contrat_famille_personne_date_naissance': '01/01/1973', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'monsieur', 'contrat_famille_personne_role_famille': 'a', 'contrat_famille_personne_roles_contrat': ['a', 's', 'p'], 'contrat_produit_code': 'emeraude'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'mme_klein', 'contrat_famille_personne_date_naissance': '01/01/1976', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'madame', 'contrat_famille_personne_role_famille': 'c', 'contrat_famille_personne_roles_contrat': ['c'], 'contrat_produit_code': 'emeraude'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'e1_klein', 'contrat_famille_personne_date_naissance': '01/01/1998', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'enfant 1', 'contrat_famille_personne_role_famille': 'e', 'contrat_famille_personne_roles_contrat': ['e'], 'contrat_produit_code': 'emeraude'}, {'contrat_code': '1234567890', 'contrat_famille_code': 'famille_klein', 'contrat_famille_personne_code': 'e2_klein', 'contrat_famille_personne_date_naissance': '01/01/2001', 'contrat_famille_personne_nom': 'klein', 'contrat_famille_personne_prenom': 'enfant 2', 'contrat_famille_personne_role_famille': 'e', 'contrat_famille_personne_roles_contrat': ['e'], 'contrat_produit_code': 'emeraude'}]
python recursion dictionary tree
Comments
Post a Comment