How to merge dictionaries of dictionaries?

后端 未结 29 3216
渐次进展
渐次进展 2020-11-22 05:13

I need to merge multiple dictionaries, here\'s what I have for instance:

dict1 = {1:{\"a\":{A}}, 2:{\"b\":{B}}}

dict2 = {2:{\"c\":{C}}, 3:{\"d\":{D}}
         


        
29条回答
  •  故里飘歌
    2020-11-22 06:09

    I have an iterative solution - works much much better with big dicts & a lot of them (for example jsons etc):

    import collections
    
    
    def merge_dict_with_subdicts(dict1: dict, dict2: dict) -> dict:
        """
        similar behaviour to builtin dict.update - but knows how to handle nested dicts
        """
        q = collections.deque([(dict1, dict2)])
        while len(q) > 0:
            d1, d2 = q.pop()
            for k, v in d2.items():
                if k in d1 and isinstance(d1[k], dict) and isinstance(v, dict):
                    q.append((d1[k], v))
                else:
                    d1[k] = v
    
        return dict1
    

    note that this will use the value in d2 to override d1, in case they are not both dicts. (same as python's dict.update())

    some tests:

    def test_deep_update():
        d = dict()
        merge_dict_with_subdicts(d, {"a": 4})
        assert d == {"a": 4}
    
        new_dict = {
            "b": {
                "c": {
                    "d": 6
                }
            }
        }
        merge_dict_with_subdicts(d, new_dict)
        assert d == {
            "a": 4,
            "b": {
                "c": {
                    "d": 6
                }
            }
        }
    
        new_dict = {
            "a": 3,
            "b": {
                "f": 7
            }
        }
        merge_dict_with_subdicts(d, new_dict)
        assert d == {
            "a": 3,
            "b": {
                "c": {
                    "d": 6
                },
                "f": 7
            }
        }
    
        # test a case where one of the dicts has dict as value and the other has something else
        new_dict = {
            'a': {
                'b': 4
            }
        }
        merge_dict_with_subdicts(d, new_dict)
        assert d['a']['b'] == 4
    
    

    I've tested with around ~1200 dicts - this method took 0.4 seconds, while the recursive solution took ~2.5 seconds.

提交回复
热议问题