Dear all
I have the following structure MyPar (this is a reproductible fictive example):
Base.@kwdef struct MyPar
n1::Int = 1
ep::Float64 = .01
co::Float64 = 1.
dg::Int = 3
it::Bool = false
end
julia> par = MyPar() # Default instance
MyPar(1, 0.01, 1.0, 3, false)
## Example of instance where some values are modified from the default
julia> par = MyPar(ep = 1.23, co = 12)
MyPar(1, 1.23, 12.0, 3, false)
And now I have the following NamedTuple, say pars, containing vectors (of equal lengths) of values for some of the elements of MyPar (the elements in pars can vary, below is just an example, other elements than ep and dg can be present):
julia> pars = (ep = [10, -7., .8], dg = [1, 25, 4])
(ep = [10.0, -7.0, 0.8], dg = [1, 25, 4])
What I would like is to automatically create a vector, say listpar, of length = length(pars[1]) whose each element “i” will contains an instance of MyPar where the values are modified from the contents of pars, i.e. in the above example of pars:
## Building listpar by hand
## (this what I would like to automatize)
ncomb = length(pars[1])
listpar = Vector(undef, n)
i = 1 ; listpar[i] = MyPar(ep = pars.ep[i], dg = pars.dg[i])
i = 2 ; listpar[i] = MyPar(ep = pars.ep[i], dg = pars.dg[i])
i = 3 ; listpar[i] = MyPar(ep = pars.ep[i], dg = pars.dg[i])
## Expected result
julia> listpar
3-element Vector{Any}:
MyPar(1, 10.0, 1.0, 1, false)
MyPar(1, -7.0, 1.0, 25, false)
MyPar(1, 0.8, 1.0, 4, false)
Do you see a way to do this automatically, given MyPar and an object pars?
I found a quasi-solution (below, probably not optimal) but I needed to use a mutable structure (MyParMut, below) and, what I did not want, to create a global variable (par_tmp, below):
Base.@kwdef mutable struct MyParMut
n1::Int = 1
ep::Float64 = .01
co::Float64 = 1.
dg::Int = 3
it::Bool = false
end
pars = (ep = [10, -7., .8], dg = [1, 25, 4]) ## A given pars
nampars = keys(pars)
npars = length(nampars)
ncomb = length(pars[1])
listpar = Vector(undef, ncomb)
for i = 1:ncomb
global par_tmp = MyParMut()
for j = 1:npars
nam = nampars[j]
val = pars[nam][i]
z = string("par_tmp.", nam, "=", val)
eval(Meta.parse(z)) ## Problem here since eval works in the global scope
end
listpar[i] = par_tmp
end
julia> listpar
3-element Vector{Any}:
MyPar(1, 10.0, 1.0, 1, false)
MyPar(1, -7.0, 1.0, 25, false)
MyPar(1, 0.8, 1.0, 4, false)
I hope my description was clear. Any idea to get an automatic way to do this (idealy from MyPar, but from MyParMut without the creation of a global variable would also be ok) would be appreciate.