Let's imagine I have an array my_array
whose elements are instances of myType
, so the array type is given by Array{myType,1}
.
Now let's say each instance of myType
within my_array
has some field x
that stores a vector of data (e.g. typeof(instance_of_myType.x) == Array{Float32,1}
).
If I know the different fields x
of each instance of the myType
struct in the Array have the same size, is there a way I can broadcast a function (e.g. averaging or summing) across the different fields x
of all the instances of myType
in the array, that will give me a single Array{Float32,1}
vector, that is the resulting of applying the function to all the x
fields of the structs within my_array
? Is there a way to do this without a for-loop, is basically what I'm asking?
This should work (unless you have overridden getproperty
for your type):
sum.(getproperty.(my_array, :x))
Here is a full example comparing broadcasting and using a comprehension:
julia> struct A{T}
x::T
end
julia> my_array = [A(collect(i:i+3)) for i in 1:3]
3-element Array{A{Array{Int64,1}},1}:
A{Array{Int64,1}}([1, 2, 3, 4])
A{Array{Int64,1}}([2, 3, 4, 5])
A{Array{Int64,1}}([3, 4, 5, 6])
julia> sum.(getproperty.(my_array, :x))
3-element Array{Int64,1}:
10
14
18
julia> [sum(v.x) for v in my_array]
3-element Array{Int64,1}:
10
14
18
Now an interesting case is if you wanted to apply a function e.g. sum
across individual elements of fields x
in the structs. You could get this result like this:
julia> sum(getproperty.(my_array, :x))
4-element Array{Int64,1}:
6
9
12
15
(note that the only difference in this case is that there is no .
after sum
)
or like this
julia> sum(v -> v.x, my_array)
4-element Array{Int64,1}:
6
9
12
15
EDIT
So a general approach would be:
julia> tmp = getproperty.(my_array, :x)
3-element Array{Array{Int64,1},1}:
[1, 2, 3, 4]
[2, 3, 4, 5]
[3, 4, 5, 6]
and now you can write:
[fun(getindex.(tmp, i)) for i in eachindex(tmp...)]
assuming that fun
takes a vector as an argument.
If you wanted to use an excellent SplitApplyCombine.jl package you could write:
fun.(invert(getproperty.(my_array, :x)))
as invert
function does exactly what you need, e.g.:
julia> invert([[1,2,3], [4,5,6]])
3-element Array{Array{Int64,1},1}:
[1, 4]
[2, 5]
[3, 6]