Skip to content

Instantly share code, notes, and snippets.

@stavxyz
Last active December 27, 2015 14:59
Show Gist options
  • Save stavxyz/7344514 to your computer and use it in GitHub Desktop.
Save stavxyz/7344514 to your computer and use it in GitHub Desktop.
map (nested) values from one dict to (differently keyed, nested) values in another dict. -- from a list of keys

like this:

The source_dict contains some values you're going to want in your new or updated target_dict, and it might look like this:

source_dict = {'key1': {
                  'key2': {
                      'key3': {
                          'key4': 'value4',
                          'key5': 'value5'
                              },
                      'key6':'value6'
                          },
                  'key7':'value7',
                  'key8':'value8'
                       },
               'key9':'value9'
               }

But you want the values in your target_dict to be nested in ['some']['out']['of']['control']['nested']['keys'].

In this case, I'll let map_values build my new dict from scratch, (you can otherwise pass in an existing target_dict).

my_new_target_dict = map_values(['key1','key2', 'key3', 'key5'], 
                                source_dict,
                                ['some', 'out', 'of', 'control', 'nested', 'keys'])

The result means

>>> source_dict['key1']['key2']['key3']['key5'] == my_new_target_dict['some']['out']['of']['control']['nested']['keys']
True
>>> my_new_target_dict 
{'some': {'out': {'of': {'control': {'nested': {'keys': 'value5'}}}}}}
>>>

Whether you build a new dict, or pass in an existing one, the non-existing keys who need nested dicts as values will be created. If you try to specify some source_keys that point to a non-existing value, the error is caught and the target value will be set to None.

def map_values(source_keys, source_dict, target_keys, target_dict={}):
fun = lambda d, k: d[k]
try:
newvalue = reduce(fun, source_keys, source_dict)
except (KeyError, TypeError) as err:
newvalue = None
def d(dictionary, n):
try:
reduce(fun, target_keys[:-1], dictionary)[target_keys[-1]] = newvalue
except KeyError as err:
newkey = err[0]
reduce(fun, target_keys[:-n], dictionary)[newkey] = {}
return d(dictionary, n-1)
return dictionary
return d(target_dict, len(target_keys))
>>> target_keys = ['i am', 'jacks', 'complete lack of']
>>> source_dict = {'jack': {'complete lack': 'surprise', 'smirking': 'revenge'}}
>>> source_keys = ['jack', 'complete lack']
>>> map_values(source_keys, source_dict, target_keys)
{'i am': {'jacks': {'complete lack of': 'surprise'}}}
>>>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment