Search code examples
pythonpython-3.5ordereddictionary

How to keep the order by updating OrderedDict


please tell me.

Description

I'd like to update the value of a variable of type OrderedDict by using the update method of dict. However, after executing the update method, the OrderedDict type of the update target variable is lost, and output as expected can not be done.

Question points:

  1. Is it faulty to lose the type of OrderedDict?
  2. Is there another way to update dict while keeping the type of OrderedDict?

Below is an example of the problem.


from collections import OrderedDict

dic = OrderedDict()

dic['a'] = 1
dic['b'] = OrderedDict()
dic['b']['b1'] = 2
dic['b']['b2'] = 3
dic['b']['b3'] = 4

print(dic)
> OrderedDict([('a', 1), ('b', OrderedDict([('b1', 2), ('b2', 3), ('b3', 4)]))]) # ok

new_dic = {'a': 2, 'b': {'b1': 3, 'b2': 4, 'b3': 5}}
print(new_dic)
> {'a': 2, 'b': {'b1': 3, 'b2': 4, 'b3': 5}}

dic.update(new_dic)

print(dic)
> OrderedDict([('a', 2), ('b', {'b1': 3, 'b2': 4, 'b3': 5})]) # NG: Type has been lost


Solution

  • An update has the effect of a rebinding of the affected keys. What you are doing in short, is:

    # ...
    dic['b'] = OrderedDict()
    # ...
    dic['b'] = {'b1': 3, 'b2': 4, 'b3': 5}
    # ...
    

    The new value of key 'b' in dic is now the common dict. You are trying to do some nested update that is not provided out of the box. You could implement it yourself along the lines of:

    def update(d1, d2):
        for k, v in d2.items():
            if k in d1 and isinstance(v, dict) and isinstance(d1[k], dict):
                update(d1[k], v)
            else:
                d1[k] = v
    

    Now you can apply it to your case:

    update(dic, new_dic)
    # OrderedDict([('a', 2), ('b', OrderedDict([('b1', 3), ('b2', 4), ('b3', 5)]))])