【问题标题】:Appending list of dictionaries with an additional key in one dictionary and a nested dict as its value在一个字典中附加一个附加键和一个嵌套字典作为其值的字典列表
【发布时间】:2019-07-10 13:33:22
【问题描述】:

我有一个架构,并且我有一个应该包含在其中的嵌套字段列表。 基本上,我所拥有的是:

[{'name': 'a', 'type': 'string'}, 
{'name': 'b', 'type': 'string'}, 
{'name': 'c', 'type': 'string'}, 
{'name': 'd', 'type': 'string'}, 
{'name': 'e', 'type': 'string'}, 
{'name': 'attr', 'type': 'string'}, 
{'name': 'f', 'type': 'string'},
{'name': 'g', 'type': 'string'}, 
{'name': 'h', 'type': 'string'}, 
{'name': 'i', 'type': 'string'}, 
{'name': 'j', 'type': 'string'}, 
{'name': 'k', 'type': 'string'}]

但是当“name”是“attr”时,我想向它添加另一个字典 k-v 对,键为“fields”,值作为另一个嵌套的字典列表,格式与上面的字典相同。这将使它看起来像:

[{'name': 'a', 'type': 'string'}, 
{'name': 'b', 'type': 'string'}, 
{'name': 'c', 'type': 'string'}, 
{'name': 'd', 'type': 'string'}, 
{'name': 'e', 'type': 'string'}, 
{'name': 'attr', 'type': 'string', 'fields': [{'name': 'aa',....}], 
{'name': 'f', 'type': 'string'},
{'name': 'g', 'type': 'string'}, 
{'name': 'h', 'type': 'string'}, 
{'name': 'i', 'type': 'string'}, 
{'name': 'j', 'type': 'string'}, 
{'name': 'k', 'type': 'string'}]

下面,master_schema_set 和nestedschemaset 都是我转换的集合。

finalschema = [{'name':l} for l in master_schema_set]
finalschemanested = [{'name':l} for l in nestedschemaset]

for i in finalschema:
    i.update({"type":'string'}) #all types will always be string
    for item,val in i.items():
        if val == 'attr':
            i.update({'fields':finalschemanested})

运行它会给我一个错误“迭代期间字典更改大小”,但最终这就是我想要的。有什么更好的方法来实现这一目标?

【问题讨论】:

    标签: python list dictionary list-comprehension


    【解决方案1】:

    试试:

    for i in finalschema:
        i.update({"type":'string'}) #all types will always be string
        if i['name'] == 'attr':
            i.update({'fields':finalschemanested})
    
    • 注意:由于错误状态,在迭代对象时不要尝试更新 dict。

    【讨论】:

      【解决方案2】:

      禁止在迭代其键/值对时修改i,解决方法是仅迭代其键,并更新i,如下所示:

      for i in finalschema:
          i.update({"type":'string'})
          for val in i.keys():
              if i[val] == 'attr':
                  i['fields'] = finalschemanested
      

      然而,这会在迭代时修改 dict,这不是一个好主意。如果有更好的方法来做你想做的事,你最好考虑一些重构。

      在您的情况下,您根本不需要迭代 i,并将您的代码更改为如下内容:

      for i in finalschema:
          i["type"] = 'string'
          if i['name'] == 'attr':
              i['fields'] = finalschemanested
      

      在旁注中,您使代码容易陷入 python 陷阱:i.update({'fields': finalschemanested}) 将在您更新的每个 dict 中放置相同的 finalschemanested 对象。如果您多次执行此操作,则您在两个不同的地方拥有相同的确切对象,这意味着修改一个地方将导致另一个地方(可能是不需要的)修改。考虑使用copy 模块:

      from copy import deepcopy
      ... 
             i.update({'fields': deepcopy(finalschemanested)})
      ...
      

      【讨论】:

        【解决方案3】:

        迭代Dict 并切换到相同的Dict 不是一个好主意。参考:Christoph Zwerschke's blog.

        您需要将您的代码更改为这种模式。这适用于列表和其他数据结构。在 python2 中,它永远不会显示为错误或警告,并且会无休止地循环运行。 参考我的一个答案Raja Sakthiyan

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-08
          • 2017-09-07
          • 1970-01-01
          • 2010-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-13
          相关资源
          最近更新 更多