2014-02-14 57 views
2

我想將簡單的平板列表複製到嵌套列表中。作爲一個例子:將平板列表複製到嵌套字典

from collections import OrderedDict 

simple_list = [5,6,7,8] 
nested_dict = OrderedDict([('item1', 1), ('item2', OrderedDict([('item3', 2), ('item4', {'item5': 3})])), ('item6',4)]) 

new_nested_dict = unflatten(nested_dict, simple_list) 
print new_nested_dict 

>>> OrderedDict([('item1', 5), ('item2', OrderedDict([('item3', 6), ('item4', {'item5': 7})])), ('item6',8)]) 

從我的研究到目前爲止,似乎生成器是一個很好的方法。但是,在查看文檔之後,我仍然不完全清楚如何實現我想要使用它們的內容。

def unflatten(nested_items, flat_data, start=0):  
    if isinstance(nested_items, OrderedDict): 
     nested_items = nested_items.values() 
    idx = start 
    for x in nested_items:   
     if isinstance(x, Iterable): 
      for i in unflatten(x, flat_data, start=idx): 
       yield i 
     else: 
      idx += 1 
      yield flat_data[idx] 

有人能指出我在做什麼錯嗎?我更願意接受一種完全不同的方法。謝謝。

回答

0

我不知道你爲什麼這樣做,但我相信這個簡單的遞歸算法的工作:

from collections import OrderedDict 

simple_list = [5,6,7,8] 
nested_dict = OrderedDict([('item1', 1), ('item2', OrderedDict([('item3', 2), ('item4', {'item5': 3})])), ('item6',4)]) 

def unflatten(nested_items, flat_data): 
    remaining_keys = list(nested_items.keys()) 
    while flat_data and remaining_keys: 
     key = remaining_keys.pop(0) 
     existing_value = nested_items[key] 
     if isinstance(existing_value, dict): 
      unflatten(existing_value, flat_data) 
     else: 
      nested_items[key] = flat_data.pop(0) 

    return nested_items 

new_nested_dict = unflatten(nested_dict, simple_list) 
assert new_nested_dict == OrderedDict([('item1', 5), ('item2', OrderedDict([('item3', 6), ('item4', {'item5': 7})])), ('item6',8)]) 

關於你現有的算法,問題可能出在isinstance(nested_items, OrderedDict)條件。您放置的物體中至少有一個不是OrderedDict,而是常規的dict。我在代碼中使用後者,因爲它是前者的超類。

此外,yield返回一個發生器值,它與懶惰列表比字典更密切相關。嘗試在更簡單的背景下與他們一起玩,看看我的意思。

0

你可以這樣做更新替代現有的字典:

from collections import OrderedDict, Mapping 

simple_list = [5,6,7,8] 
nested_dict = OrderedDict([('item1', 1), ('item2', OrderedDict([('item3', 2), ('item4', {'item5': 3})])), ('item6',4)]) 

def update(d, u): 
    for k, v in d.iteritems(): 
     if isinstance(v, Mapping): 
      update(d.get(k), u) 
     else: 
      try: 
       d[k] = u.pop(0) 
      except IndexError: 
       break 
    return d    

update(nested_dict, simple_list) 
print nested_dict 
# OrderedDict([('item1', 5), ('item2', OrderedDict([('item3', 6), ('item4', {'item5': 7})])), ('item6', 8)]) 

注意這個更新替代現有的有序字典,而不是產生新的嵌套字典。

如果你想訪問舊字典,只需使用deepcopy首先製作一個副本。另請注意,您傳遞的列表將通過依次彈出每個元素來消耗。再一次,如果您需要保留這些數據 - 請使用切片或其他列表副本製作其副本。

雖然產生髮電機是有效的,但是就地更新通常更有效。