3

I have a nested dictionary as below

entry = {
    0: {"Q": 0},
    1: {"W": 2, "E": 3, "N": 5, "S": 4, "Q": 0},
    2: {
        "N": {
            "Q": {"E"}
        }
    },
}

When I try to access only the keys for the key 1, I get the following:

>>> print(entry[1].keys())
dict_keys(['W', 'E', 'N', 'S', 'Q'])

But for key 2 it only returns the top key and not the nested key.

>>> print(entry[2].keys())
dict_keys(['N'])  

Why is it not returning the nested key of the dictionary?

6
  • 3
    Why do you think it is supposed to return nested keys? dict.keys() method doesn't do that. Commented Aug 8, 2018 at 18:56
  • 1
    keys returns the keys of the dict keys is called on, not all keys contained at an arbitrary point in the dict. while "Q" is a key which happens to be in the dict, from the perspective of entry[2] it's part of the values Commented Aug 8, 2018 at 18:57
  • 1
    So what would you expect entry.keys() to return? Commented Aug 8, 2018 at 19:01
  • @taras , ok.. how to access them here Commented Aug 8, 2018 at 19:22
  • @Karamzov, entry[2]['N']['Q'] will give you 'E' Commented Aug 8, 2018 at 20:08

6 Answers 6

6

keys()doesn't work that way.

keys()

Return a new view of the dictionary’s keys

Your nested dictionnary is a completely separate dict, and you can get its own keys with its own keys() method :

entry[2]['N'].keys()

If you want to recursively get all the keys inside nested dictionnaries, you will have to implement a method for that :

entry = {0: {"Q": 0},
         1: {"W": 2, "E": 3, "N": 5, "S": 4, "Q": 0},
         2: {"N": { "Q":{"E"}}},
}


def rec_keys(dictio):
    keys = []
    for (key,value) in dictio.items():
        if isinstance(value, dict):
            keys.extend(rec_keys(value))
        else:
            keys.append(key)
    return keys

print(rec_keys(entry))
# ['Q', 'Q', 'W', 'N', 'S', 'E', 'Q']
Sign up to request clarification or add additional context in comments.

1 Comment

ok..is it possible to access nested key value without using the main key , ie here fetch E by accessing Q
1

When you run print(entry[2].keys())

you're asking python "What keys exist in the data corresponding to key '2'? (which in your case is another dictionary)" The answer to which is just 'N'. This is because

entry[2]

is

{"N": { "Q":{"E"}}

which has the single key 'N' and the data '{"Q":{"E"}}'

2 Comments

ok , so inorder to access the nested key you need to create a method
@Gunnar this helps OP understand why there are no nested keys returned currently, but can you add to your answer how you'd access the nested keys? I believe that was the original question.
1

dict.keys only returns the top level keys of the dictionary. If you want to get all nested keys of a dictionary, you will need to define your own function.

# interface for dictionary-like objects
from collections.abc import Mapping

def nested_keys(d) -> set:
    """
    Return a set containing all nested keys.
    """
    # If it is not a dict-like object, return an empty set
    if not isinstance(d, Mapping):
        return set()

    keys = d.keys()
    for v in d.values():
        # Update the keys set with the keys in each value by using the union (or) operator: |
        keys |= nested_keys(v)

    return keys

2 Comments

what is this isinstance ?
It is an abstract base class (similar to an interface in other languages). So isinstance(d, Mapping) is similar to isinstance(d, dict), except this will also work with other mapping types (like the Counter, defaultdict, OrderedDict classes in the collections module for instance)
1

if you wanted to check all nested keys, you could create a loop function that checks the type of your looked up data and iterates over it if it is another dictionary, like

def print_nested_keys(d):
    for k in d.keys():
        print(k)
        if type(d[k]) == dict:
            print('nested dict detected - recursing...')
            print_nested_keys(d[k])

here, whenever one of the keys in your dictionary points to another dictionary, you call the function recursively to read through the lower-level dictionary keys. of course, you could always append the keys that you find in a list to return by your function in the end, if you want such a list.

Comments

0

For only keys, Use simple recorsive function:

def recursive_items(dict_name):
    for key, value in a.items():
        if type(value) is dict:
            yield (key)
            yield from recursive_items(value)

# print the keys 
for key in recursive_items(a):
   print(key)

This function will benefit for any nested dictionary

Comments

0

Depending on what your goals are, here are functions to collect a nested list of dict keys and pretty-print this list:

from typing import Union

def list_keys(hashmap: dict) -> list[str]:
    """Collect list of nested key names."""
    keys = []
    for k in hashmap.keys():
        keys.append(k)
        if type(hashmap.get(k)) is dict:
            keys.append(fieldnames(hashmap.get(k)))
    return keys

def pprint(obj: Union[list,dict]) -> None:
    """Pretty print dicts as JSON."""
    print(json.dumps(obj, indent=4))
    return None

entry = {
    0: {"Q": 0},
    1: {"W": 2, "E": 3, "N": 5, "S": 4, "Q": 0},
    2: {
        "N": {
            "Q": "E"
        }
    },
}

keys = list_keys(entry)
print(keys, '\n', entry)
pprint(keys)
pprint(entry)

Here, I have removed the depth-4 level so that it will properly serialize to JSON for printing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.