Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How do I get a list of all keys in a dictionary of dictionaries, at a given depth [closed]

Tags:

python

If I have a dictionary of dictionaries, of arbitrary depth, how could I list all of the keys that are in the dictionary, at a given depth? or get a list of the keys in the dictionary and their depths?

For example, a simple dictionary would be:

    dict_o_dicts = {'a': {1:'bob', 2: 'fred', 3: 'henry'},
                    'b': {2:'fred',3: 'henry', 4: 'pascale'} 
                          }

and I'd like a command that does something along the lines of: print keys_at_depth(dict_o_dicts, 0) would return: ['a', 'b'] and print keys_at_depth(dict_o_dicts, 1) would return [1,2,3,4]

I can recursively walk the dictionary to find the maximum depth of the dictionary, but as soon as I try and report both the depth and the key values I end up breaking the recursion.

Thanks

like image 696
Malcolm Brooks Avatar asked Dec 06 '13 14:12

Malcolm Brooks


3 Answers

This routine will recursively return a dictionary of sets of the keys at each depth:

def keys_by_depth(dict_, depth=0, output=None):
    if output is None:
        output = {}
    if not depth in output:
        output[depth] = set()
    for key in dict_:
        output[depth].add(key)
        if isinstance(dict_[key], dict):
            keys_by_depth(dict_[key], depth+1, output)
    return output

Gives the output:

{0: {'b', 'a'}, 1: {1, 2, 3, 4}}

Note that this will work with a mix of dictionary and non-dict values at each level. For only keys at a given depth, you can call and access in one go:

>>> print(keys_by_depth(dict_o_dicts)[1])
{1, 2, 3, 4}
like image 133
jonrsharpe Avatar answered Nov 15 '22 07:11

jonrsharpe


The assumption is that, all levels have valid dicts

dict_o_dicts = {'a': {1:'bob', 2: 'fred', 3: 'henry'},
                'b': {2:'fred',3: 'henry', 4: 'pascale'} }
from itertools import chain
def keys_at_depth(d, l):
    if l == 0: return d.keys()
    elif l > 0: return set(chain.from_iterable([keys_at_depth(d[k], l - 1) for k in d]))

print keys_at_depth(dict_o_dicts, 1)

Output

set([1, 2, 3, 4])
like image 20
thefourtheye Avatar answered Nov 15 '22 09:11

thefourtheye


Recursive approach:

def key_at_depth(dct, dpt):
    if dpt > 0:
        return [
            key
            for subdct in dct.itervalues()
            for key in key_at_depth(subdct, dpt - 1)
        ]
    else:
        return dct.keys()

dict_o_dicts = {
    'a': {1: 'bob', 2: 'fred', 3: 'henry'},
    'b': {2: 'fred', 3: 'henry', 4: 'pascale'},
}

key_at_depth(dict_o_dicts, 0)

Out[69]: ['a', 'b']

key_at_depth(dict_o_dicts, 1)

Out[70]: [1, 2, 3, 2, 3, 4]
like image 31
koffein Avatar answered Nov 15 '22 08:11

koffein