5

I'm trying to create a recursive function that takes a JSON dictionary and stores any value with key names 'rate' into a list. I will then take that list and find the lowest value. My code looks like this right now, but is producing multiple empty lists within the list.

def recurse_keys(df):
    rates = []
    for key, value in df.items():
        if key == 'rate':
            rates.append(value)
        if isinstance(df[key], dict):
            recurse_keys(df[key])
5
  • 3
    Because you're doing rates = [] on each recursive call. Commented Feb 1, 2016 at 7:37
  • pass rates as an argument to the recursive function Commented Feb 1, 2016 at 7:39
  • Each time you call recurse_keys, it's creating a new rates list which is initially empty. Presumably this is not what you want. Commented Feb 1, 2016 at 7:39
  • @MarounMaroun I don't think that's the problem, the problem is that nothing is returned and that the result from the recursive calls is discarded. Commented Feb 1, 2016 at 7:40
  • @timgeb correct, missed that. Commented Feb 1, 2016 at 7:41

4 Answers 4

18

You need to combine the results from the recursion, and return it:

def recurse_keys(df):
    rates = []
    for key, value in df.items():
        if key == 'rate':
            rates.append(value)
        if isinstance(df[key], dict):
            rates += recurse_keys(df[key])
    return rates
Sign up to request clarification or add additional context in comments.

4 Comments

@Casey df[key] and value are the same, no? Is there a reason to mix?
@Fabricator is this method preferred over the suggested below (passing rates)? This method would seem less intuitive, but maybe I'm wrong?
@Jason, both methods work. I prefer to use fewer arguments. Plus this required minimum change from OP's original code.
@Jason I think you are right. They are the same value. I'll fix that.
2
  1. extend your result list with the result from the recursive call
  2. don't forget to return your result

Code:

def recurse_keys(df):
    rates = []
    for key, value in df.items():
        if key == 'rate':
            rates.append(value)
        if isinstance(df[key], dict):
            rates += recurse_keys(df[key])
    return rates

Comments

1

You can also initialize the rates list outside of the recursive function and pass it to the function, as list is a mutable datastructure, it'll be passed as reference. Like this (not tested though):

def recurse_keys(df, rates):
    for key, value in df.items():
        if key == 'rate':
            rates.append(value)
        if isinstance(df[key], dict):
            recurse_keys(df[key], rates)

def calling_method():
    rates = [] 
    recurse_keys(df, rates)

Comments

0

you need pass rates as rates, it seems in every recursion you do create new rates list.

def recurse_keys(df, rates=[]):
    for key, value in df.items():
        if key == 'rate':
            rates.append(value)
        if isinstance(df[key], dict):
            recurse_keys(df[key], rates)
    return rates

result = recurse_keys(df)
min(result)

4 Comments

be very careful about that mutable default argument
I have never faced problem with this usage but it does not mean I will not indeed, thanks @Rogalski, @ timgeb. I will be more careful.
@ŁukaszRogalski I checked that and several other pages linked in there! it made me realise that in this example simply calling recurse_keys(df[key]) instead of recurse_keys(df[key], rates) would still work, but only the first time it is called.

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.