# Assigning vector fields from a struct to a vector

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.               # Default values for test purposes
B = 2.
C = 3.
Int_Field = 10
D = 4.
E = 5.
F = 6.
variables = MyStruct(;A, B, C, Int_Field, D, E, F)
return variables
end

function main()                               # Test program
@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()
``````

Use `name_list = [:A, :C, :F]` then you can do, for instance, `getfield(variables, name_list`. Also the master list is `fieldnames(MyStruct)`.

1 Like

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.               # Default values for test purposes
B = 2.
C = 3.
Int_Field = 10
D = 4.
E = 5.
F = 6.
variables = MyStruct(;A, B, C, Int_Field, D, E, F)
return variables
end

function main()                               # Test program
@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 = getfield(variables, name_list)

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:
 setindex!(A::Vector{Float64}, x::Vector{Float64}, i1::Int64)
@ Base .\array.jl:843
 main()
 top-level scope
``````

This runs:

``````function main()                               # Test program

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
@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
``````

Assuming that you have one name per line, then just

``````push!(name_list, Symbol(ln) )
``````

(within the file, don’t have a `:`). Note that `?Symbol` does tell you how to construct a symbol from a string.

1 Like

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

1 Like