Accessing key, value in a nested dictionary

2019-07-15 05:08发布

I know questions regarding accessing key, value in a nested dictionary have been asked before but I'm having some trouble with the following piece of my code:

For accessing the keys and values of a nested dictionary as follows:

example_dict = {'key_outer_01': {'key_inner_01': 'value_inner_01'},
                'key_outer_02': {'key_inner_02': 'value_inner_02'}}

I have the following piece of code:

def get_key_value_of_nested_dict(nested_dict):
    for key, value in nested_dict.items():
        outer_key = None
        inner_key = None
        inner_value = None
        if isinstance(value, dict):
            outer_key = key
            get_key_value_of_nested_dict(value)
        else:
            inner_key = key
            inner_value = value
        return outer_key, inner_key, inner_value

The output that I'm getting is:

    key_outer_01 None None

What am I doing wrong here?

5条回答
一纸荒年 Trace。
2楼-- · 2019-07-15 05:36
example_dict = {'key_outer_01': {'key_inner_01': 'value_inner_01'}, 'key_outer_02': {'key_inner_02': 'value_inner_02'}}

def get_key_value_of_nested_dict(nested_dict, outer_key=None):
    inner_key = None
    inner_value = None
    for key, value in nested_dict.items():

        if isinstance(value, dict):
            outer_key = key
            return get_key_value_of_nested_dict(value, key)
        else:
            inner_key = key
            inner_value = value
        return outer_key, inner_key, inner_value

print get_key_value_of_nested_dict(example_dict)

Output:

('key_outer_01', 'key_inner_01', 'value_inner_01')
查看更多
走好不送
3楼-- · 2019-07-15 05:41

One thing for sure is you need a return here

if isinstance(value, dict):
        outer_key = key
        get_key_value_of_nested_dict(value)

return get_key_value_of_nested_dict(value)
查看更多
The star\"
4楼-- · 2019-07-15 05:49

If you have a nested dict, you need a nested for loop:

def print_items(nested_dict):

    for key, dictionary in my_dict.items():

        for inner_key, value in dictionary.items():
            print(key, inner_key, value)

my_dict = {"a": {"b": "c", "d": "e"}, "f": {"g": "h"}}
print_items(my_dict)

This prints:

a b c
a d e
f g h
查看更多
三岁会撩人
5楼-- · 2019-07-15 05:53
def get_key_value_of_nested_dict(nested_dict):
    rv = []
    for outer_key, value in nested_dict.items():
        try:
            # first we leap
            inner_kvs = get_key_value_of_nested_dict(value)
            for inner_keys, inner_value in inner_kvs:
                rv.append(([outer_key]+inner_keys, inner_value))
        except AttributeError:
            # then ask for forgiveness
            rv.append(([outer_key], value))
    return rv

You get a list of tuples. In each tuple the first element is a list of your keys and the second is the final value.

example_dict = {'key_outer_01': {'key_inner_01': 'value_inner_01'},
                'key_outer_02': {'key_inner_02': 'value_inner_02'}}

get_key_value_of_nested_dict(example_dict)

# output
[(['key_outer_01', 'key_inner_01'], 'value_inner_01'),
 (['key_outer_02', 'key_inner_02'], 'value_inner_02')]

To simply get a list of tuples with no inner list of keys just change the function a bit:

def get_key_value_of_nested_dict(nested_dict):
    rv = []
    for outer_key, value in nested_dict.items():
        try:
            inner_kvs = get_key_value_of_nested_dict(value)
            for i_kvs in inner_kvs:
                rv.append((outer_key,) + i_kvs)
        except AttributeError:
            rv.append((outer_key, value))
    return rv

get_key_value_of_nested_dict(example_dict)

# output
[('key_outer_01', 'key_inner_01', 'value_inner_01'),
 ('key_outer_02', 'key_inner_02', 'value_inner_02')]
查看更多
ゆ 、 Hurt°
6楼-- · 2019-07-15 06:01

In your recursive call, you are setting outer_key, inner_key and inner_value to None. But in the if isintance(value, dict), you are only redifining outer_key to key. You might want to assign the new values of inner_key and inner_value.

Assign new value to inner_key and inner_value ! Such as :

example_dict = {'key_outer_01': {'key_inner_01': 'value_inner_01'},
                'key_outer_02': {'key_inner_02': 'value_inner_02'}}

def get_key_value_of_nested_dict(nested_dict):
    for key, value in nested_dict.items():
        outer_key = None
        inner_key = None
        inner_value = None
        if isinstance(value, dict):
            outer_key = key
            _, inner_key, inner_value = get_key_value_of_nested_dict(value)
        else:
            inner_key = key
            inner_value = value
        return outer_key, inner_key, inner_value

print get_key_value_of_nested_dict(example_dict)
# outputs : ('key_outer_01', 'key_inner_01', 'value_inner_01')

I believe we need more information whereas all the edge-cases to know if this code is good or not.


I tried for fun some kind of improvement, tell me if it suits your case better than your original code.

example_dict = {'key_outer_01': {'key_inner_01': 'value_inner_01', 'key_inner_02' : 'value_inner_02'},
                'key_outer_02': {'key_inner_02': 'value_inner_02'},
                'key_outer_03' : None}

def get_k_v_of_inner(nested_dict):
    for k, v in nested_dict.items():
        if isinstance(v, dict):
            for k_nested, v_nested in v.items():
                yield {k : {k_nested : v_nested}}
        else:
            # do_something, or simply ignore if not nested dict.
            pass

gen = get_k_v_of_inner(example_dict)

for c, value in enumerate(gen):
    print '#{} : {}'.format(c, value)

# outs : #0 : {'key_outer_01': {'key_inner_02': 'value_inner_02'}}
         #1 : {'key_outer_01': {'key_inner_01': 'value_inner_01'}}
         #2 : {'key_outer_02': {'key_inner_02': 'value_inner_02'}}
查看更多
登录 后发表回答