2016-01-21 93 views
0

我期待写一个递归函数:如何编写将字典拆分为字典数组的递归Python函数?

arguments: d, dictionary 

result: list of dictionaries 

def expand_dictionary(d): 
    return [] 

功能递归经过一个字典和使用_,除了它扩展了嵌套列表入阵变平嵌套的对象,包括父标签。

想象从文档创建关系模型。

下面是一个例子的输入和输出:

original_object = { 
    "id" : 1, 
    "name" : { 
    "first" : "Alice", 
    "last" : "Sample" 
    }, 
    "cities" : [ 
    { 
     "id" : 55, 
     "name" : "New York" 
    }, 
    { 
     "id" : 60, 
     "name" : "Chicago" 
    } 
    ], 
    "teachers" : [ 
    { 
     "id" : 2 
     "name" : "Bob", 
     "classes" : [ 
     { 
      "id" : 13, 
      "name" : "math" 
     }, 
     { 
      "id" : 16, 
      "name" : "spanish" 
     } 
     ] 
    } 
    ] 
} 

expected_output = [ 
    { 
    "id" : 1, 
    "name_first" : "Alice", 
    "name_last" : "Sample" 
    }, 
    { 
    "_parent_object" : "cities", 
    "id" : 55, 
    "name" : "New York" 
    }, 
    { 
    "_parent_object" : "cities", 
    "id" : 60, 
    "name" : "Chicago" 
    }, 
    { 
    "parent_object" :"teachers", 
    "id" : 2, 
    "name" : "Bob" 
    }, 
    { 
    "parent_object" :"teachers_classes", 
    "id" : 13, 
    "name" : "math" 
    }, 
    { 
    "parent_object" :"teachers_classes", 
    "id" : 16, 
    "name" : "spanish" 
    } 
] 

当前正用于平坦化的代码是:

def flatten_dictionary(d): 
    def expand(key, value): 
     if isinstance(value, dict): 
     return [ (key + '_' + k, v) for k, v in flatten_dictionary(value).items() ] 
     else: 
     #If value is null or empty array don't include it 
     if value is None or value == [] or value == '': 
      return [] 
     return [ (key, value) ] 

    items = [ item for k, v in d.items() for item in expand(k, v) ] 

    return dict(items) 
+0

是你的'original_obejct'字典吗?所以应该在第一行''id':1'之后有'逗号'? – Ali

+0

正确,为语法错误表示歉意。 –

+1

看起来像是在摧毁信息:如果你有多个教师,你能告诉每个教师从期望的输出中教授哪些课程吗? –

回答

0

这将做

def expand_dictionary(d,name=None,l=None): 
    obj = {} 
    if l == None: 
     l = [obj] 
    else: 
     l.append(obj) 

    prefix = (name+'_'if name else '') 
    if prefix: obj['_parent_object'] = name 

    for i, v in d.iteritems(): 
     if isinstance(v, list): 
      map(lambda x:expand_dictionary(x,prefix+i,l),v) 
     elif isinstance(v, dict): 
      obj.update(flatten_dictionary({i: v})) 
     else: 
      obj[i] = v 
    return l 
+0

没有得到正确的输出。我发布了我的解决方案,我一直在努力。 –

+0

除非你指的是排序,它的输出与所需的匹配。谢谢。 – MIE

0

通过它工作后这里是我想到的。可能会被显着优化。根据@ paulo-scardine的评论,我添加了父主键来保留关系模型。很想听到优化的想法。

def expand_dictionary(original_object, object_name, objects=None): 
    if objects is None: 
    objects = [] 
    def flatten_dictionary(dictionary): 

    def expand(key, value): 
     if isinstance(value, dict): 
     return [ (key + '_' + k, v) for k, v in flatten_dictionary(value).items() ] 
     else: 
     #If value is null or empty array don't include it 
     if value is None or value == [] or value == '': 
      return [] 
     return [ (key, value) ] 

    items = [ item for k, v in dictionary.items() for item in expand(k, v) ] 
    return dict(items) 

    original_object_root = flatten_dictionary(original_object).copy() 
    original_object_root['_meta_object_name'] = object_name 

    for key,value in original_object_root.copy().items(): 
    if isinstance(value, dict): 
     flatten_dictionary(value, objects) 
    if isinstance(value, list): 
     original_object_root.pop(key) 
     for nested_object in value: 
     nested_object['_meta_parent_foreign_key'] = original_object_root['id'] 
     nested_object['_meta_object_name'] = object_name + "_" + key 
     expand_dictionary(nested_object, object_name + "_" + key, objects) 

    objects.append(original_object_root) 

    return objects