How to efficiently transform vector of structures?

How to efficiently transform vector of structures without unnecessary allocation? We have two structures:

struct ApiData
  name::String
  reload::Vector{ApiReload}
  values::Vector{Float64}
end

struct ApiReload
  status::String
  time::Sting  #Transform to sturcture "TimeOfDay"
end

which make the vector a = Vector{ApiData}. Now we want to transform the vector a into vector b which has the form of three structures:

struct Data
  name::String
  reload::Vector{Reload}
  values::Vector{Float64}
end

struct Reload
  status::String
  time::TimeOfDay
end

struct TimeOfDay
  minutes::Array{Int}
  hours::Array{Int}
end

Vector b has the form of Vector{Data}, with percentage members in the Data structure (name =1%, reload=4% and values 95%).

What have you tried and what do you mean with unnecessary allocation? Wouldn’t it be sufficient to preallocate the vector b and fill it in a loop?

@laborg In fact, I have a third structure, yet. For C API.

struct C_ApiData
  name::Ptr{Cwchar_t}
  reloadLength::Csize_t
  reload::Vector{C_ApiReload}
  valuesLength::Csize_t
  values::Vector{Cdouble}
end

And I’m looking for the most optimal way (design Pattern).

You haven’t specified how fields should be transformed, so I’m just guessing on the similarity of type names, but then its not clear how ApiReload with a single String should map to Reload having Array{Int} for minutes and hours.

Now, looking at your last line:

Vector{Data} , with percentage members in the Data structure…

should the transform contain any calculations as well, or is it merely a structural transformation?

Yes, there will be a parse function that transforms String to structure TimeOfDay. Further e.g. a[1].reload[1].status to enum

@enum Status lunch=1 evening=2

etcetera …

I’d go with:

parsetime(t::String) = TimeOfDay([1],[1])
transform(x::ApiReload) = Reload(x.status, parsetime(x.time))
transform(x::ApiData) = Data(x.name, transform.(x.reload), x.values)

a = ApiData[
  ApiData("ap1",
    ApiReload[ApiReload("st1","ti1"), ApiReload("st2","ti2")],
    Float64[1.,2.,3.,4.]),
  ApiData("ap2",
      ApiReload[ApiReload("st3","ti3")],
      Float64[1.,2.])
  ]

b = transform.(a)

If you want less allocations and more speed you can replace the broadcasting by manual preallocation of the vectors and explicit loops.

It would be easier for others to help if you present your current solution and describe what you’d like to improve. (nota bene: I’m still learning Julia, so I might have missed something, but till now I’ve never come across a generic structural transformation design pattern).

1 Like