将平面列表复制到嵌套的dict中

时间:2014-02-14 17:39:39

标签: python dictionary nested

我正在尝试将简单的平面列表复制到嵌套列表中。举个例子:

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

从我的研究到目前为止,似乎发电机是一种很好的方法。但是,在查看了doc之后,我仍然不完全清楚如何使用它们来实现我想要做的事情。

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]

有人可以指出我在这里做错了吗?我更愿意接受一种完全不同的方法。感谢。

2 个答案:

答案 0 :(得分: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返回一个Generator值,它与懒惰列表比与dicts更密切相关。尝试在更简单的环境中玩它们,看看我的意思。

答案 1 :(得分: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)])

请注意,这会更新现有的有序字典而不是产生新的嵌套字典。

如果您想要访问旧的dict,只需先使用deepcopy复制它。另请注意,您传递的列表将依次弹出每个元素。再次,如果您需要保留该数据 - 使用切片或列表的其他副本制作副本。

虽然产生发电机是有效的,但通常更新效率更高效。