【问题标题】:Nested dictionaries iterations within dictionaries using for loop使用for循环在字典中嵌套字典迭代
【发布时间】:2020-04-08 12:07:59
【问题描述】:

共有三种不同的嵌套字典:

dict1={'g1': {'s1': 'checked', 's2': '0', 'Both':'checked'}, 'g2': {'s1': '0', 's2':'checked', 'Both': 'checked'}, 'g3': {'s1': 'checked', 's2': 'checked', 'Both': 'checked'}}
dict2={'g1': {'s1': '11', 's2': '', 'Both': '13'}, 'g2': {'s1': '', 's2': '22', 'Both':'23'}, 'g3': {'s1':'31', 's2': '32', 'Both': '33'}}
dict3={"s1": {"PS":'value1'}, "s2": {"PS": 'value2'}, "Both": {"PS": 'value3'}}

所需的嵌套字典是dict4。 (注意:dict1dict2 的格式,即{'g1': {'s1': "xxxx",'s2':'xxxy'}},其中xxxxxxxy 是来自以下给定条件的值。)

描述:键和值是通用的。并且上述三个字典所需的所需输出也必须是嵌套字典,条件为 if value=='checked' in dict1 然后 dict3 具有新键 'Msg' 和来自 dict2 的值必须添加相同的嵌套键到所需的嵌套字典dict4,其父键来自dict1

我的代码:

dict4={}  # declaring desired dictionary
for nkey,nvalue in dict1.items():
    tempDict={} #temporary dictionary to store all checked from dict1
    for key,value in nvalue.items():
        if value=='checked':
            tempDict[key]=dict3[key]
            tempDict[key]['Msg']=dict2[nkey][key]
    #in prescribed format assigning dict4
    dict4[nkey]=tempDict

上述代码的错误输出:(错误的'Msg' 值)

dict4 = {'g1': {'s1': {'PS': 'value1', 'Msg': '31'}, 'Both': {'PS': 'value3', 'Msg': '33'}}, 'g2': {'s2': {'PS': 'value2', 'Msg': '32'}, 'Both': {'PS': 'value3', 'Msg': '33'}}, 'g3': {'s1': {'PS': 'value1', 'Msg': '31'}, 's2': {'PS': 'value2', 'Msg': '32'}, 'Both': {'PS': 'value3', 'Msg': '33'}}}

正确和期望的输出:(带有正确的'Msg'

dict4 = {'g1': {'s1': {'PS': 'value1', 'Msg': '11'}, 'Both': {'PS': 'value3', 'Msg': '13'}}, 'g2': {'s2': {'PS': 'value2', 'Msg': '22'}, 'Both': {'PS': 'value3', 'Msg': '23'}}, 'g3': {'s1': {'PS': 'value1', 'Msg': '31'}, 's2': {'PS': 'value2', 'Msg': '32'}, 'Both': {'PS': 'value3', 'Msg': '33'}}}

根据上面的代码,我试图将所有检查过的 dict1 存储到临时字典中,然后添加键 'Msg'(新键)和来自 dict2 的值,然后以所需格式分配 dict4 (来自dict1 的键和来自临时字典的值,即tempDict)。

问题:正如我所观察到的那样,它会在更改时从所需的 dict4tempDict 值覆盖 'Msg',然后在 for 循环内部反映 dict4 值(因为我通过打印来调试代码所有阶段的值)。

请澄清并提出可能的解决方案,以及为什么当tempDict 上的值发生变化时,它反映到已经分配给dict4 中的前一个键值,即当tempDict 更改'Msg' 为@987654354 时@ 然后它也会更改 g1g2 中的值。

我已经尝试用tempDict.clear() 方法代替tempDict={} 然后dict4 输出是这样的:

dict4={}  # declaring desired dictionary
for nkey,nvalue in dict1.items():
    tempDict={} #temporary dictionary to store all checked from dict1
    for key,value in nvalue.items():
        if value=='checked':
            tempDict[key]=dict3[key]
            tempDict[key]['Msg']=dict2[nkey][key]
    #in prescribed format assigning dict4
    dict4[nkey]=tempDict
    tempDict.clear()  

上面的输出:(错误)

dict4 = {'g1': {}, 'g2': {}, 'g3': {'s1': {'PS': 'value1', 'Msg': '31'}, 's2': {'PS': 'value2', 'Msg': '32'}, 'Both': {'PS': 'value3', 'Msg': '33'}}},

是否存在从价值问题或我写错逻辑的地方分配的内存?

正确且期望的输出:(带有正确的'Msg'

dict4 = {'g1': {'s1': {'PS': 'value1', 'Msg': '11'}, 'Both': {'PS': 'value3', 'Msg': '13'}}, 'g2': {'s2': {'PS': 'value2', 'Msg': '22'}, 'Both': {'PS': 'value3', 'Msg': '23'}}, 'g3': {'s1': {'PS': 'value1', 'Msg': '31'}, 's2': {'PS': 'value2', 'Msg': '32'}, 'Both': {'PS': 'value3', 'Msg': '33'}}}

代码 3:(相同的输出)

dict4={}
for nkey,nvalue in dict1.items():                 
  for key,value in nvalue.items():                        
    if value=='checked':
      try:
        dict4[nkey][key]=dict3[key]
      except:
        dict4[nkey]={}
      dict4[nkey][key]=dict3[key]
      dict4[nkey][key]['Msg']=dict2[nkey][key]

【问题讨论】:

    标签: python dictionary for-loop nested


    【解决方案1】:

    问题在于 Python 的 dict 类型是可变类型。使用tempDict[key]=dict3[key],您会将对现有dict3[key] 的“引用”放入tempDict[key]。如果您通过从 dict 的引用访问它来更改对象,那么这些更改将在任何地方“可见”(因为 dict3[key]tempDict[key] 都引用同一个对象)。

    换句话说,您可以通过“外部”dict 中的引用访问“内部”dict,因此任何应用于“内部”dict 的修改都将是“可见”的,无论您采用哪种方式用于访问它。毕竟,这只是同一个对象。在copy 之后,您有两个对象(两个“内部”dict)和两个“外部”dict 分别指代它们。

    有关 Python 中可变/不可变类型的更多信息:例如,Immutable vs Mutable types

    关于解决方案:好消息,如果您不希望dict3[key]tempDict[key] 都引用同一个对象,您可以通过dict.copy 方法创建一个副本。所以在你的第一个代码中,你唯一需要改变的是

    tempDict[key]=dict3[key]
    

    tempDict[key]=dict3[key].copy()
    

    你会得到你想要的输出。

    如果您的dict 包含更多的可变类型,而您想要更改这些类型,则必须使用copy.deepcopy 创建每个“层”的副本。

    【讨论】:

    • “他的问题在于 Python 的 dict 类型是可变类型。因此,您不会将键和值放入新的 dict4 而是对象本身。”可变性在这里无关紧要,不可变类型也会发生同样的事情。不可变类型只是缺少 mutator 方法
    • 是的,但这只是因为你不能改变整数。但是语义仍然是相同的,实际的整数对象和实际的 dict 对象作为值进入。 你不能改变一个整数。 IOW,无论该对象是可变的还是不可变的,总是“仅引用”对象进入。
    • @finefoot 非常感谢,它确实帮助我获得了所需的输出。但是有一个疑问,因为字典是可变的,那么它在“tempDict”中迭代时如何指向该对象的相同引用(或id)。
    • @juanpa.arrivillaga 是否意味着当我从 tempDict 将字典作为值分配给 dict4 时,它只是分配参考?那我们怎么能说它是可变的呢?
    • @finefoot 现在更清晰了!我以前不知道这一点。谢谢你:)
    猜你喜欢
    • 2021-12-03
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2019-03-29
    • 1970-01-01
    相关资源
    最近更新 更多