How to assign a struct array to a field of another struct array?

83 visualizaciones (últimos 30 días)
Hello everybody, thanks in advance for your help with this!
So I'm trying to assign a struct array to a field of another struct array when both have the same size and obviously trying to avoid a for loop.
It looks something like this
data % This is a struct array that doesnt have the field trait yet
trait % this is a struct array of the same length of data
assert(length(data) == length(trait))
data.t = trait % this fails with --> Scalar structure required for this assignment.
[data.t] = [trait] % this fails with --> Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
[data.t] = [trait] % this fails with --> Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
[data.t] = deal(trait) % works but assigns the whole trait struct array to the field t in each element of data
Im pretty sure that if trait was a cell where each element of the cell was each of the elements in the struct array then this should work
[data.t] = cellTrain{:}
But I cant figure out a way to expand the trait struct-array into a cell as struct2cell expands every field in every struct of the struct array into cells.
Finally for completion the result should be equivalent to this simple for loop but hopefully a bit more efficient
for i = 1:length(data)
data(i).t = trait(i);
end
Thanks once again for all the help!
  2 comentarios
madhan ravi
madhan ravi el 22 de Feb. de 2019
attach your struct as .mat file
Juan Sierra
Juan Sierra el 22 de Feb. de 2019
Heres a small script that you can run if you want to try ;)
load('testData.mat')
idx = sum(datenum([uniqueTrait.date])' < datenum([data.date]), 1);
trait = uniqueTrait(idx);
% data.t = trait; % this fails with --> Scalar structure required for this assignment.
% [data.t] = [trait]; % this fails with --> Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
% [data.t] = [trait]; % this fails with --> Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
% [data.t] = deal(trait); % works but assigns the whole trait struct array to the field t in each element of data
%% the result of this for loop should be the end result!
for i = 1:length(data)
data(i).t = trait(i);
end
It seems like a very simple thing to be honest but I cant figure out a way to avoid that loop XD

Iniciar sesión para comentar.

Respuesta aceptada

Stephen23
Stephen23 el 22 de Feb. de 2019
Editada: Stephen23 el 22 de Feb. de 2019
You just need to use a comma-separated list
on the both sides of the allocation. MATLAB supports two ways to generate a comma-separated list from one array:
  1. from a cell array, or
  2. from the field of a structure (we can use this on the LHS)
and usually the first one is simpler to use, so this is what we will use on the RHS. Note that the fact that your array is also a structure is totally irrrelevant: the same methods can to be applied regardless of what class of array you want to allocate.
>> data = struct('A',{1,2,3},'B',{4,5,6})
1x3 struct array containing the fields:
A
B
>> trait = struct('Z',{7,8,9})
trait =
1x3 struct array containing the fields:
Z
>> C = num2cell(trait); % convert your array to a cell array of scalars.
>> [data.t] = C{:} % use a comma-separated list.
data =
1x3 struct array containing the fields:
A
B
t
>> data(3).t.Z
ans = 9
  2 comentarios
Juan Sierra
Juan Sierra el 22 de Feb. de 2019
Ohhhh my!!!
Thanks so much! this was very helpful!
Honestly I thought num2cell was for numeric arrays only! It states on the documentation that it is to convert numeric arrays but if I apply isnumeric to trait it returns 0.
Well it works :)
Thanks again!
Stephen23
Stephen23 el 22 de Feb. de 2019
Editada: Stephen23 el 22 de Feb. de 2019
" It states on the documentation that it is to convert numeric arrays..."
The MATLAB documentation is surprisingly (how can I put this politely) ... flexible with its terminology. Most likely this is for historic reasons, from when MATLAB really did only support numeric and character array classes. In the last few years the input/output definitions have gained lists of allowed classes, but inside the text itself terms like "must be a matrix" are still used without further clarification (is my structure matrix a matrix? Is my graphics handle matrix a matrix? etc.).
Anyway, when you scroll down to the input definition, it lists these accepted classes:
Data Types: double | single | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | logical | char | string | struct | cell | categorical | datetime | duration | calendarDuration | function_handle

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Entering Commands en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by