Hi I am have trouble assigning vector fields from a struct (myStruct) to a vector (Base_Case). Please find code below. Essentially, I want to match the numerical values of the vector fields in the struct that match my “mask” name_list (which is a string vector). I wonder if anyone can help or perhaps I am trying to do the impossible?
using Parameters
@with_kw struct MyStruct # could have up to 350 fields, not all vectors
A :: Vector{Float64}
B :: Vector{Float64}
C :: Vector{Float64}
Int_Field::Int64
D :: Vector{Float64}
E :: Vector{Float64}
F :: Vector{Float64}
end
function load_data() # This function loads data OR creates an instance (could be substitued with reading a file)
A = zeros(1)
B = zeros(1)
C = zeros(1)
D = zeros(1)
E = zeros(1)
F = zeros(1)
A[1] = 1. # Default values for test purposes
B[1] = 2.
C[1] = 3.
Int_Field = 10
D[1] = 4.
E[1] = 5.
F[1] = 6.
variables = MyStruct(;A, B, C, Int_Field, D, E, F)
return variables
end
function main() # Test program
variables = load_data() # Load data from function load_data()
@unpack A, B, C, Int_Field, D, E, F = variables
name_list =["A", "C", "F"] # typically 3 element string vector although could be 4 or 5 (user defined)
master_list = ["A","B","C","D","E","F"] # this is a fixed master list string vector (same names as vector fields in MyStruct)
Base_Case = zeros(3) # Float64 vector - to be found
for n = 1:3
for m = 1:6
if master_list[m] == name_list[n]
# Base_Case[n] = name_list[n] ### How to assigned Base_Case[n] to the appropriate vector value (numercial) contained in the struct??
println(name_list[n])
end
end
end
end
main()
Many thanks for quick response. I am not sure I fully understand your response. Please see below modified code as I thought you suggested, with error below. If you could modify it would be appreciated:
using Parameters
@with_kw struct MyStruct # could have up to 350 fields, not all vectors
A :: Vector{Float64}
B :: Vector{Float64}
C :: Vector{Float64}
Int_Field::Int64
D :: Vector{Float64}
E :: Vector{Float64}
F :: Vector{Float64}
end
function load_data() # This function loads data OR creates an instance (could be substitued with reading a file)
A = zeros(1)
B = zeros(1)
C = zeros(1)
D = zeros(1)
E = zeros(1)
F = zeros(1)
A[1] = 1. # Default values for test purposes
B[1] = 2.
C[1] = 3.
Int_Field = 10
D[1] = 4.
E[1] = 5.
F[1] = 6.
variables = MyStruct(;A, B, C, Int_Field, D, E, F)
return variables
end
function main() # Test program
variables = load_data() # Load data from function load_data()
@unpack A, B, C, Int_Field, D, E, F = variables
name_list =[:A, :C, :F] # typically 3 element string vector although could be 4 or 5 (user defined from a read in file - different every time)
master_list = fieldnames(MyStruct)
Base_Case = zeros(3)
Base_Case[1] = getfield(variables, name_list[1])
end
main()
ERROR: LoadError: MethodError: Cannot `convert` an object of type Vector{Float64} to an object of type Float64
Closest candidates are:
convert(::Type{T}, ::T) where T<:Number at number.jl:6
convert(::Type{T}, ::Number) where T<:Number at number.jl:7
convert(::Type{T}, ::Base.TwicePrecision) where T<:Number at twiceprecision.jl:250
...
Stacktrace:
[1] setindex!(A::Vector{Float64}, x::Vector{Float64}, i1::Int64)
@ Base .\array.jl:843
[2] main()
@ Main c:\Users\peter\Documents\Julia_Code\GH_Model_Final\Test_Read.jl:39
[3] top-level scope
@ c:\Users\peter\Documents\Julia_Code\GH_Model_Final\Test_Read.jl:42
in expression starting at c:\Users\peter\Documents\Julia_Code\GH_Model_Final\Test_Read.jl:42
function main() # Test program
variables = load_data() # Load data from function load_data()
name_list =[:A, :C, :F, :No] # typically 3 element string vector although could be 4 or 5 (user defined from a read in file - different every time)
master_list = fieldnames(MyStruct)
base_case = Vector{Any}(undef, 3)
for (i,n) in enumerate(name_list)
if n in master_list
base_case[i] = getfield(variables, n)
end
end
return base_case
end
although whether it is what you want, I don’t know.
Thanks. Your solution is almost what I want although I need some clarification on name_list if possible. In your example you have explicitly defined the contents of name_list, with the : before each element and with :No at the end of the vector(last element). I am not sure what the : and :No does? Also, in my actual program, I will be reading name_list from a text file as follows (see below), rather than being able to define it explicitly in the program. How do I make my read-in name_list compatible with your program? A typical data file (Name_List.txt) might be:
A
C
F
name_list = String[] # initialize empty string array
open("Name_List.txt", "r") do f
for ln in eachline(f)
push!(name_list,ln)
end
end
Thanks again for taking on this challenge. You have certainly increased my understanding of some interesting Julia commands
Good to hear that we’re making progress. Regarding your question, this would be my REPL session to find out:
julia> typeof(:A)
Symbol
julia> typeof(:No)
Symbol
help?> Symbol
search: Symbol
Symbol
The type of object used to represent identifiers in parsed julia code (ASTs). Also often used as a name or label to identify an entity (e.g. as a dictionary key). Symbols can be entered
using the : quote operator:
julia> :name
:name
julia> typeof(:name)
Symbol
julia> x = 42
42
julia> eval(:x)
42
Symbols can also be constructed from strings or other values by calling the constructor Symbol(x...).
Symbols are immutable and should be compared using ===. The implementation re-uses the same object for all Symbols with the same name, so comparison tends to be efficient (it can just
compare pointers).
Unlike strings, Symbols are "atomic" or "scalar" entities that do not support iteration over characters.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Symbol(x...) -> Symbol
Create a Symbol by concatenating the string representations of the arguments together.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> Symbol("my", "name")
:myname
julia> Symbol("day", 4)
:day4
Note how you can do Symbol("A") and that :No is just another symbol not some “closing bracket” as you thought.
Thanks for that. I must remember to use the REPL help more often. I am a self taught FORTRAN programmer still coming to terms with many of Julia’s intricacies’. Could you shed some light on how to read name_list in from a file. I tried putting a colon in front of each of the vector fields in the text file but to no avail(see file below at end of program). It seems my name_list input vector does not contains Symbols (rather it is just a string array, albeit with colons in front of each element), making the iterative comparison impossible. Is there a way to make my name_list vector the same “type” as yours and allow the iterative comparison to be made? Perhaps this is a dumb question and a new approach is required. Thanks again for your efforts. Feel free to bail out if this is taking too much of your time.
function main() # Test program
variables = load_data() # Load data from function load_data()
@unpack A, B, C, Int_Field, D, E, F = variables
#name_list =[:A, :C, :F] # typically 3 element string vector
#@show name_list
name_list = [] # initialize empty array
open("Name_List.txt", "r") do f
for ln in eachline(f)
push!(name_list,ln)
end
end
@show name_list
master_list = fieldnames(MyStruct)
base_case = Vector{Any}(undef, 3)
for (i,n) in enumerate(name_list)
if n in master_list
base_case[i] = getfield(variables, n)
end
end
@show base_case
end
main()
name_list = Any[":A", ":Ma", ":B", ":F"]
base_case = Any[#undef, #undef, #undef]
3-element Vector{Any}:
#undef
#undef
#undef
Yeh that works! Without your help I would not have found this solution. My problem is “you don’t know what you don’t know” and this is particularly the case when basic tutorials do not touch on such subjects. Best regards and thanks again. Peter