0

I have the following Python 2.7.16 dictionary with default values:

settings = {
    'alpha': {
        'Add': [],
        'Delete': [],
        'Patch': {
            'Software': False,
            'Hardware': False
        }
    },
    'beta': {
        'Flash': [],
        'Definitions': {
            'Occur': False,
            'Define': False,
            'Disable': False,
            'Enable': False
        }
    },
    'gamma': {
        'Allow': {},
        'Block': {}
    }
}

I want to update the settings dictionary with values from a new dictionary, as defined:

new_settings = {
    'alpha': {
        'Delete': ['model', 'structure'],
        'Patch': {
            'Software': True
        }
    },
    'beta': {
        'Definitions': {
            'Define': True,
            'Disable': True
        }
    },
    'gamma': {
        'Allow': {
            'Update': True
        }
    }
}

The end-result would be the following merged dictionary:

settings = {
    'alpha': {
        'Add': [],
        'Delete': ['model', 'structure'],
        'Patch': {
            'Software': True,
            'Hardware': False
        }
    },
    'beta': {
        'Flash': [],
        'Definitions': {
            'Occur': False,
            'Define': True,
            'Disable': True,
            'Enable': False
        }
    },
    'gamma': {
        'Allow': {
            'Update': True
        },
        'Block': {}
    }
}

I tried:

configuration = settings.copy()
configuration.update(new_settings)

But that would result of some of the keys being removed from setting dictionary.

Thank you.

Floren
  • 113
  • 11
  • What's your code so far? We aren't just going to write code for you- you have to make a valid attempt at solving the problem before coming here. – Kevin Sheng Nov 22 '20 at 04:42
  • I updated the OP with a code example. – Floren Nov 22 '20 at 04:49
  • This code isn't using anything specific to Python2, so why can't you upgrade? And, if you read the docs for the update function, you'd probably see the issue that it doesn't recursively update nested values – OneCricketeer Nov 22 '20 at 04:52
  • @OneCricketeer this code is used in a specific Python 2.7.16 environment, I cannot upgrade. I will accept a solution for this specific Python version. – Floren Nov 22 '20 at 05:21
  • Python3 dictionaries work the same way, anyway, so doesn't really matter – OneCricketeer Nov 22 '20 at 05:22
  • This isn't the exact answer since you also have lists but as mentioned, the solution is going to require recursion https://stackoverflow.com/questions/20656135/python-deep-merge-dictionary-data – OneCricketeer Nov 22 '20 at 05:28
  • Alternatively, you can define some `get_settting` function that attempts a lookup from the "override" values, but falls back to the "defaults" in case the lookup fails – OneCricketeer Nov 22 '20 at 05:30

2 Answers2

1

You need to update nested dict recursively as following.

import collections

def update(d, u):
    for k, v in u.iteritems():
        if isinstance(v, collections.Mapping):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v

    return d

update(settings, new_settings)

print(settings)
Yuri R
  • 311
  • 2
  • 9
0
new_settings = {
        'alpha': {
            'Delete': ['model', 'structure'],
            'Patch': {
                'Software': True
            }
        },
        'beta': {
            'Definitions': {
                'Define': True,
                'Disable': True
            }
        },
        'gamma': {
            'Allow': {
                'Update': True
            }
        }
    }

    settings = {
        'alpha': {
            'Add': [],
            'Delete': [],
            'Patch': {
                'Software': False,
                'Hardware': False
            }
        },
        'beta': {
            'Flash': [],
            'Definitions': {
                'Occur': False,
                'Define': False,
                'Disable': False,
                'Enable': False
            }
        },
        'gamma': {
            'Allow': {},
            'Block': {}
        }
    }



    for key, value in new_settings.items():

        if value.__class__.__name__ == "dict":
        # check if element is a dictionary
            for key2, value2 in value.items():
                # if dictionary get key and value for that dictionary
                if value2.__class__.__name__ == "dict":
                    # check if there is nested dictionary
                    settings[key][key2].update(value2)
                    # if it exists update the lements within dictionary

                elif value.__class__.__name__ in ("list", "tuple"):
                    settings[key][key2] += value2
                    # check if there is inner list or tuple and combine

                else:
                    settings[key][key2] = value
                    # if inner value is string or numeric replace



        elif value.__class__.__name__ in ("list", "tuple"):
            # if first element is list or tuple combine
            settings[key] += value

        else:
            # if first element is string or numeric replace
            settings[key] = value


    # this should work perfect for 3 layerd dictionaries beyond that requires your own modifications
    print(settings)
Baryon
  • 112
  • 10
  • This works well, except updating the `beta` `Definitions` values. the beta dictionary will become: ` 'beta': { 'Definitions': { 'Define': True, 'Disable': True } } ` – Floren Nov 22 '20 at 05:13
  • I updated the `new_settings` dictionary into OP, with a better example. – Floren Nov 22 '20 at 05:23