Gabriel Machado
Gabriel Machado

Reputation: 493

How to create a struct or type from a dictionary in Julia?

I have imported a bunch of data from a .mat file (MATLAB format) and they come as dictionarys, but it's kind of anoying using them, so I wanted to pass it for a struct. I know I can do this:

using MAT

struct model
    trans
    means
    vars
end

vars = matread("data.mat")
hmm1=model(vars["hmm1"]["trans"],vars["hmm1"]["means"],vars["hmm1"]["vars"])

Is there a way to do this without typing every key of the dictionay?

Upvotes: 4

Views: 2119

Answers (3)

Jelmer Mulder
Jelmer Mulder

Reputation: 99

I came across the same issue: loading a Matlab file using MAT.jl which returns a nested dictionary. Instead of converting the dictionary to a (nested) struct, I wrote the following function to recursively search any (nested) path within the dictionary.

function superget(fault::Dict{String, Any}, path)
    # Use 'get' recursively to find nested path in fault
    if !occursin("/", path) && !occursin(".", path)
        return get(fault, path, missing)
    elseif occursin("/", path)
        splitpath = split(path, "/")
        superget(get(fault, popfirst!(splitpath), missing), join(splitpath, "/"))
    elseif occursin(".", path)
       splitpath = split(path, ".")
       superget(get(fault, popfirst!(splitpath), missing), join(splitpath, "."))
    end
end

Example usage

using MAT
vars = MAT.matread(path2file)

# defining path with '/'
range_x = superget(vars, "path/to/parameter/range_x")

# or use '.' 
range_x = superget(vars, "path.to.parameter.range_x")

Upvotes: 0

Benoit Pasquier
Benoit Pasquier

Reputation: 2995

If you're only worried about the dot-access syntax à la hmm1.means, you could instead use a NamedTuple:

julia> vars = Dict("hmm1"=>Dict("trans"=>1, "means"=>2, "vars"=>3)) ;

julia> hmm1 = (; (Symbol(k) => v for (k,v) in vars["hmm1"])...)
(trans = 1, vars = 3, means = 2)

julia> hmm1.means
2

(Taken and adapted from Julia discourse: How to make a named tuple from a dictionary?.)

Upvotes: 1

Cameron Bieganek
Cameron Bieganek

Reputation: 7664

There's probably no way to avoid directly accessing the relevant keys of your dictionary. However, you can simplify your life a little by making a custom Model constructor that takes in a Dict:

using MAT

struct Model
    trans
    means
    vars
end

function Model(d::Dict)
    h = d["hmm1"]
    Model(h["trans"], h["means"], h["vars"])
end

d = matread("data.mat")

Model(d)

Upvotes: 1

Related Questions