我正在尝试将简单的平面列表复制到嵌套列表中。举个例子:
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]
有人可以指出我在这里做错了吗?我更愿意接受一种完全不同的方法。感谢。
答案 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复制它。另请注意,您传递的列表将依次弹出每个元素。再次,如果您需要保留该数据 - 使用切片或列表的其他副本制作副本。
虽然产生发电机是有效的,但通常更新效率更高效。