Package or Function to find and access keys in a nested dicts

Continuing the discussion from Looking for a key in a nested dict:

This does not work for me, my Dict has three sub-layers of Dicts.
In my case I can reach the value of interest by the following command:

molar_mass_ = hydrogen_dict["TRANSPORT"]["viscosity"]["dilute"]["molar_mass"]

If I call the function above as follows:

molar_mass_ = retrieve(hydrogen_dict, "molar_mass")

The result is:

 typeof(molar_mass_)
Nothing

Are you sure your example is completely free of typos? It works fine for me:

julia> hydrogen_dict = Dict("TRANSPORT" => Dict("viscosity" => Dict("dilute" => Dict("molar_mass" => 2.016))))
Dict{String, Dict{String, Dict{String, Dict{String, Float64}}}} with 1 entry:
  "TRANSPORT" => Dict("viscosity"=>Dict("dilute"=>Dict("molar_mass"=>2.016)))

julia> retrieve(hydrogen_dict, "molar_mass")
2.016

Note that

  1. a Dicts elements are not sorted
  2. and your function will only return the first key it encounters.

This could easily cause problems when you have duplicated keys on different levels of a nested dict.

1 Like

Yes, probably no typos, as far as I can see :frowning:

using PyCall
teqp = PyCall.pyimport("teqp")
hydrogen_dict = teqp.collect_component_json(["Hydrogen"], string(teqp.get_datapath()))[1]

P.S.:
Installation of “teqp”

ENV["CONDA_JL_USE_MINIFORGE"] = "1"
import Conda; Conda.pip("install", "teqp")

Maybe they aren’t Dict types? But rather something unique to this PyCall and python combination. What does your structure look like?

typeof(hydrogen_dict)
Dict{Any, Any}

And the nested ones?

transport_ = pureJSON["TRANSPORT"]
typeof(transport_)
Dict{Any, Any}
viscosity_  = transport_["viscosity"]
typeof(viscosity_)
Dict{Any, Any}
dilute_     = viscosity_["dilute"]
typeof(dilute_)
Dict{Any, Any}

Okay, then I think Package or Function to find and access keys in a nested dicts - #2 by stillyslalom is probably the correct explanation.

1 Like

Sorry, I saw that there are two versions of the function, the second version
works fine.

I have added a check, if only one instance of the key_of_interrest is included in the Dict,
if this is the case the output is a scalar:

function _retrieve(dict, key_of_interest, output = []) # default value is an empty array
    for (key, value) in dict
        println("key: ", key, ", typeof(key): ", typeof(key))
        if key == key_of_interest
            push!(output, value)
        end
        if value isa AbstractDict
            _retrieve(value, key_of_interest, output)
        end
    end
    if size(output)[1] == 1
        output = output[]
    end
    return output
end