2016-01-21 91 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