1

i need to build a function that return me the depth of a dictonary. for example :

 dict_depth({1:"a",2:"b"}) 
 depth = 0

 dict_depth({1: {1:"a",2:"b"},2:"b"}) 
depth =  1

 dict_depth({1: {1:"a",2:"b"},2: {1:{1:"a",2:"b"},2:"b"}}) 
depth = 2

but i need to add another condition where if the function get a non dict value the function will return me a string that say ("this is not a dict") insted of typeError. but as you can see i cant think of a way to do it with my function because even if the function get a dict value at the end because of the Recursion the function will get a non dict value.

what do you think may fix the problem? thank you guys

-this is my code, it does work

def dict_depth(d):
    if isinstance(d, dict):
        if not d:
            return 1
        else:
            return 1 + max(dict_depth(value) for value in d.values())
    else:
        return -1
matszwecja
  • 6,357
  • 2
  • 10
  • 17
Ori Hemo
  • 11
  • 2
  • 1
    Does this answer your question? [Know the depth of a dictionary](https://stackoverflow.com/questions/23499017/know-the-depth-of-a-dictionary) – 0stone0 May 23 '23 at 14:20
  • Please use correct upper case letters. It is hard to read your text. Also use PEP8 code guideline to improve readability of your code. It is also hard to read. – buhtz May 23 '23 at 14:46

4 Answers4

0

You can add an optional parameter that indicates whether this is the top-level call (which doesn't allow non-dict) or recursion (which does).

Also, the value for leaves should be 0, not -1.

def dict_depth(d, toplevel=True):
    if isinstance(d, dict):
        if not d:
            return 1
        else:
            return 1 + max(dict_depth(value, toplevel=False) for value in d.values())
    elif toplevel:
        return "this is not a dict"
    else:
        return 0
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You could write it like this

def dict_depth(d):
    return max((1 + dict_depth(v) for v in d.values() if isinstance(v, dict)),
               default=0)

then, if necessary, catch the AttributeErrors raised when the passed argument does not have values.

def print_dict_depth(d):
    try:
        print(dict_depth(d))
    except AttributeError:
        print("This is not a dictionary")  # or raise a new error with better explanation
Stuart
  • 9,597
  • 1
  • 21
  • 30
0

depth has a simple recursive encoding -

def depth(t):
  if isinstance(t, dict):
    return 1 + max(depth(x) for x in t.values())
  else:
    return -1
print(depth({1:"a",2:"b"}))
# 0

print(depth({1: {1:"a",2:"b"},2:"b"}))
# 1

print(depth({1: {1:"a",2:"b"},2: {1:{1:"a",2:"b"},2:"b"}}))
# 2

print(depth("foo"))
# -1

print(depth(100))
# -1
Mulan
  • 129,518
  • 31
  • 228
  • 259
-2

No need to over-engineer.

def dict_depth_wrapper(d):
    if not isinstance(d, dict):
        return "this is not a dict"
    else:
        dict_depth(d)
matszwecja
  • 6,357
  • 2
  • 10
  • 17
  • there is a problem with your answer , because my function always get the value of the key untill the value is not a key anymore, but it doesnt mean i want that the function will end i want it to keep searching for the maximum depth – Ori Hemo May 23 '23 at 14:23
  • Even though the OP didn't state it, I would recommend something along the lines of `return f"Expected dict, got {type(d)}"` so it's easier to debug if a bad argument is given. – B Remmelzwaal May 23 '23 at 14:26
  • 1
    Don't return strings as quasi-exceptions. Raise a real exception. – chepner May 23 '23 at 14:26
  • @OriHemo You can add it after your function and call wrapper instead. You could also write it as nested functions, that's pretty much up to you. You can also change the naming to `dict_depth` and `dict_depth_recursive`, so you won't have to refactor every call. – matszwecja May 23 '23 at 14:26
  • @chepner That's explicitly what OP wanted. – matszwecja May 23 '23 at 14:27
  • @chepner probably, but I think you should take this discussion to him. – matszwecja May 23 '23 at 14:52