2

I have a python dict (read from a json file) like the one below:

{ 'a' : 
    { 'b' : 
        { 'c': 3, 
          'd': 4} 
    } 
} 

What is the best way to identify the total number of keys, including sub-keys? In the above example the desired answer would be 4 ('a','b','c','d'). Is there a way to do this without just creating a for loop and iterating through?

martineau
  • 119,623
  • 25
  • 170
  • 301
WolVes
  • 1,286
  • 2
  • 19
  • 39

2 Answers2

2

You can use recursion:

def key_num(d):
   return sum(not isinstance(b, dict) or 1 + key_num(b) for b in d.values())

data = {'a': {'b': {'c': 3, 'd': 4}}}
print(key_num(data))

Output:

4
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
2

You could use the object_hook parameter that json.load() and json.loads() accept to just watch what is being decoded and count the number of keys in each dictionary.

The optional object_hook parameter is a function that will be called with the result of any JSON object literal decoded (a dict).

I got the idea of doing this from @Mike Brennan's answer to another (Python 2) JSON-related question How to get string objects instead of Unicode from JSON? — which, as I said initially, is that using object_hook is a convenient way to "watch" what's being loaded by the json.loads() function.

import json


def count_keys(json_repr):
    count = 0

    def _decode_dict(a_dict):
        nonlocal count
        count += len(a_dict)
        return {}  # Return value doesn't matter.

    json.loads(json_repr, object_hook=_decode_dict)  # Return value ignored.
    return count



json_str = '''\
{ "a" :
    { "b" :
        { "c": 3,
          "d": 4}
    }
}'''

print(count_keys(json_str))  # -> 4
martineau
  • 119,623
  • 25
  • 170
  • 301