Linked Questions

Popular Questions

I have two dictionaries, that are of similar structure...meaning they(should) have the same key structure, even within nested keys. Also, these dicts could have almost any type of nested structure...list, dict, etc... I want to be able to traverse these dictionaries, and grab the two values and return them from a function.

Simple Example:

dict_a = {'a':1, 'b':2, 'c':{'d':3}}
dict_b = {'a':2, 'b':4, 'c':{'d':6}}
#Note the structure is the same for these dicts
#I want to be able to do something like:
>>get_values( dict_a, dict_b)
[(1,2),(2,4),(3,6)]

I came up with a solution to it myself by traversing one dictionary, and appending each key(or index if it encounters a list) into a list...as a sort of key-path:

key_map = []#A list of all key-paths for a dictionary
generate_key_paths(dict_a, [], key_map)
def generate_key_paths(value, key_list,key_map ):

    new_list = [item for item in key_list]
    if isinstance( value, dict):
        #Handle list
        for key, val in value.iteritems():
            new_list.append( key)
            self._generate_key_paths( val, new_list, key_map )
            new_list = [item for item in key_list]

    elif isinstance( value, list ):
        #Handle list
        for idx,item in enumerate(value):
            new_list.append( idx )  
            self._generate_key_paths( item, new_list, key_map )
            new_list = [item for item in key_list]
    else:
        #Handle data--reached farthest point you can go
        #So just append (key-path, value) to key_map
        key_map.append((new_list, value ) )

And then once you have a list of key-path,value tuples...take the path, and try to reach it on the second dictionary to get its value...

val_list = []
for item in key_map:
    value = get_value( item[0] )
    if value is not None:
        val_list.append( (item[1], value ) )
def get_value( key_list ):
    value = dict_b
    for item in key_list:
        try:
            value = value[item]
        except:
            value = None
            break
    return value

This works quite well for all structures a dictionary could have, but it seems like a lot of work. Is there a more pythonic way of achieving this? Is there a faster, more efficient way?

EDIT: I'm looking for a value that isn't a list or a dict, so when these values are reached, it should iterate inside them, until it finds a value. It is guaranteed that if it's a list, it will be a list of dicts, so there should always be some sort of key:value relationship to follow.

For example a possible dict could look like this:

dict_a = {'a':1, 'b':2, 'c':[{'d':5},{'e':6}]}

dict_b = {'a':2, 'b':4, 'c':[{'d':10},{'e':12}]}

Answer: [(1,2), (2,4), (5,10), (6,12)]

Related Questions