I’m a mechanical engineering student and I come from MATLAB, so I am sorry for my heresies.
I have a structure with 13 fields, each of which is a structure with 10 fields, for example:
mutable struct b
b1::some type
b2::some type
b3::some type
...
b10::some type
end
struct a
a1::b
a2::b
a3::b
...
a13:b
end
I have to loop on the 13 fields to assign a new value at the field b4 for example, how can I do it in Julia?
In MATLAB I used to create an array of strings containing the 13 field names of the struct a:
afieldnames = ["a1" "a2" ... "a13"]
and then with the following loop I can access the field of b4 for each field of a as:
for i = 1:13
a.(afieldnames(i)).b4 = somevalue
end
Before we get into how to do this, are you sure this is actually what you want? You’re jumping through a lot of hoops to do something that would be trivial to do with a regular old vector. For example, what if you were to just replace a with a Vector{b} and b with a Vector{some type}? Then you could loop over the elements of a without needing to do anything special. And, as a bonus, the resulting code will be shorter and much more efficient. I’m happy to provide more detail if that’s a direction you want to go in.
First of all thank you for the attention! It is true that julia comunity is very friendly!!
Shurely I could do it with some vectors and matrices, but it would be messier I guess.
I am trying to implement the dempster’s model to perform some calculations on a human body inertial properties. In order to do that the body is divided in 14 segments, each of which has its own length, mass, centre of mass,…
The structure a mentioned above would be a collector of the segments, so:
struct a
head&neck::b
right fore arm::b
right thigh::b
.....
end
while the structure b a collector of the properties, so
mutable struct b
segment length::float64
segment mass::float64
....
end
The structure is mutable since some values of the field are calculated in a function, it works, but I dont know if it is the best way to do it.
Since a lot of calculations are the same for each segment, for example the length of the segment is related to the height of the subject, I would like to compute them in the for loop in the fields of the structure a.
If there is a cleaner way to implement I would really appreciate your advices. My goal for this implemantation of the dempster’s model is to make it easy to read, not pure performance, since all the calculations can be done by hand in less than an hour.
Just to chime in here with my opinion: @rdeits has it right. This is probably much better suited for a vector of vectors or a matrix. You’ll get the advantages of optimized looping/indexing, for one, and I’ll bet you’ll get improved cache locality as well.
Might I suggest a 13 (row) x 10 (column) matrix of some type, where each row corresponds to a single a struct and the columns are elements in your b structs? I suggest this because Julia’s matrices are column-optimized and it sounds like you’re looping through a given element in b across all as.
If you want labels for the arrays for easier indexing, check out NamedArrays.jl (disclaimer: I haven’t used it) or even DataFrames.jl.
My issue with using matrices and vectors is that retrieving information for a single segment would be less clean since I would have to call the centre of mass, the moment of inertia, the mass, the length,…, while with the structure it would be done in a single line of code (a.arm would contain all the informations about the arm of the subject). By the way if it is really that bad to do what I meant to do I will switch to matrix.
I came up with another good reason to have something similar to this.
Suppose that I have to perform some experimental tests on a set of specimens with different properties. In MATLAB I used to create a structure organized as follows:
struct infos
temperature::Float64
time::Float64
relativeHumidity::Float64
loggedData1::Array{Float64,2}
loggedData2::Array{Float64,2}
....
end
struct data
specimen1::infos
specimen2::infos
specimen3::infos
...
specimenN::infos
end
Then if I had to perform the same calculation for all the specimens I would use the for loop mentioned above. Should I do it in an other way?
If each “body” is some overall info about the body (height, weight, subject identity, etc…) and a list of segments, you could probably organize it as
struct Segment
length::Float64
mass::Float64
end
struct Body
height::Float64
segments::Vector{Segment}
end
and now body.segments[i] gives you the i-th segment. Note that you probably don’t need to make Segment mutable: you can just set the i-th element of the vector to a new Segment struct, without mutating the old one (it tends to be more efficient).
Using @kristoffer.carlsson’s suggestion is, I think, the idiomatic way to do this. When you have a collection of like-typed objects, create some collection of them, whether it’s a vector, a set, or something else. In my experience, Julia can optimize better for collections than it can some arbitrary structure, and you ultimately end up with cleaner / more idiomatic code.