【问题标题】:Copy flat list into a nested dict将平面列表复制到嵌套字典中
【发布时间】:2014-03-14 04:54:51
【问题描述】:

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

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]

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

【问题讨论】:

    标签: python dictionary nested


    【解决方案1】:

    我不知道你为什么要这样做,但我相信这个简单的递归算法有效:

    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 值,它与惰性列表的关系比与字典的关系更密切。尝试在更简单的上下文中与他们一起玩,以了解我的意思。

    【讨论】:

      【解决方案2】:

      您可以通过以下方式更新现有字典:

      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 先复制它。另请注意,您传递的列表将通过依次弹出每个元素来消耗。再一次,如果您需要保留该数据 - 使用切片或列表的其他副本制作它的副本。

      虽然产生一个生成器是高效的,但就地更新通常更有效。

      【讨论】:

        猜你喜欢
        • 2016-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-31
        • 2018-08-02
        • 2021-10-18
        • 2020-10-15
        相关资源
        最近更新 更多