Question: Function not returning a value?

Could anyone help with this function? I would like to get a return value, but it returns nothing. The below is my function:

function retrieve(dict, key_of_interest, value_of_interest)
  for (key, value) in dict
    if key == key_of_interest && value == value_of_interest 
      @show dict["name"] #just to check
      return(dict["name"])
    end 
    if value isa Vector
      for child in value
        retrieve(child, key_of_interest, value_of_interest)
      end
    end
  end
end
dict = Dict("id" => 1, "name" => "name1", "children" => [Dict("id" => 2, "name" => "name2", "children" => [], ), Dict("id" =>3, "name" => "name3", "children" => [])])

dict contains id and children, a vector of Dictionary. Each children would repeatedly contain a vector of Dictionary; but here in this sample example, I made it short.

retrieve(dict, "id", 1) # It returns a value
retrieve(dict, "id", 2) # It does not return a value

I would like to get “name2” from retrieve(dict, "id", 2). Could anyone explain why it returns Nothing and guide me how to solve this?

Though I haven’t worked your code in detail, I’m pretty sure what’s happening is you iterate through the for (key, value) loop without ever hitting a return statement. Eventually you get through the last iterate, (maybe get false for both if statements), and reach the final end for the function definition. Since the last statement executed was the for loop, its value nothing is returned by your function.

1 Like

I think there’s got to be a better tree structure available than coding one with nested Dicts.

1 Like

The offending code here is for child in value where the last iteration does not return anything.

Ideally you’d want to convert this data structure to a tree so that you can use iterators to look for stuff more easily.

2 Likes

And if you know the value of interest then just return it :wink:

retrieve(dict, key_of_interest, value_of_interest) = value_of_interest
1 Like

Ah, I actually made things simple to solve this issue and forgot the original purpose of this function. There is another key that I want to return. I will update the original post in a couple of minutes.

Use JSON3. It will decode into your own structs.

I solved the issue. The main problem was the fact that I thought whenever I called return in a nested function, the entire function would finish…haha. Thank you @owiecc and John_Gibson for comments from where I was able to start tackling the issue. I did not carefully look into tree structure; and @Jeff_Emanuel, with JSON3 I couldn’t figure out how to load JSON as a tree structure. If anyone gives me how to convert nested Dictionary (potentially from a JSON file) into a tree, it will be great. Anyway my new function contains new three lines:

function retrieve(dict, key_of_interest, value_of_interest)
  for (key, value) in dict
    if key == key_of_interest && value == value_of_interest
      return(dict["name"])
    end
    if value isa Vector
      for dict in value
        label = retrieve(dict, key_of_interest, value_of_interest)
        if !isnothing(label) #
          return(label)  # return value here.
        end #
      end
    end
  end
end

Of course, there might be potential issues. One would be the case where a downstream nested Dictionary contains the same “id”. In such a case, the “name” of the downstream Dictionary will not be retrieved.

struct Node
       id
       name
       children::Vector{Node}
end

js = "{\"name\":\"name1\",\"id\":1,\"children\":[{\"name\":\"name2\",\"id\":2,\"children\":[]},{\"name\":\"name3\",\"id\":3,\"children\":[]}]}"

using JSON3, StructTypes
StructTypes.StructType(::Type{Node}) = StructTypes.Struct()
tree = JSON3.read(js,Node)
println(tree)
Node(1, "name1", Node[Node(2, "name2", Node[]), Node(3, "name3", Node[])])

Thank you. I will try: I will need some time to get into a tree structure and how to manage it, and this seems a good starting point.