From: Mike Pesavento on
I have repeatedly run into this problem and don't know if it is an issue with my coding style, if I'm missing something obvious, or if it just isn't possible and I should look for other ways.

I am looping through function calls that return a struct. I would like to build those structs into an array, but consistently get the "??? Subscripted assignment between dissimilar structures" error. I have followed Loren's excellent guide on initializing arrays of structs, but all of the solutions seem to require knowing all of the fieldnames of the target struct.

Example:
myFunction returns a struct with 8 fields, but I do not know them beforehand
%======
m=struct([]);
for n=1:numN
m(n)=myFunction(x);
end
%======
returns:
> ??? Subscripted assignment between dissimilar structures

Initializing with
m(numN)=struct('alwaysHere',[]);
where the fieldname alwaysHere is, well, always there, gives me the same error.

Is there a way around this? Thanks!
From: Doug Schwarz on
In article <him5vp$m36$1(a)fred.mathworks.com>,
"Mike Pesavento" <cogit080(a)yahoo.com> wrote:

> I have repeatedly run into this problem and don't know if it is an issue with
> my coding style, if I'm missing something obvious, or if it just isn't
> possible and I should look for other ways.
>
> I am looping through function calls that return a struct. I would like to
> build those structs into an array, but consistently get the "??? Subscripted
> assignment between dissimilar structures" error. I have followed Loren's
> excellent guide on initializing arrays of structs, but all of the solutions
> seem to require knowing all of the fieldnames of the target struct.
>
> Example:
> myFunction returns a struct with 8 fields, but I do not know them beforehand
> %======
> m=struct([]);
> for n=1:numN
> m(n)=myFunction(x);
> end
> %======
> returns:
> > ??? Subscripted assignment between dissimilar structures
>
> Initializing with
> m(numN)=struct('alwaysHere',[]);
> where the fieldname alwaysHere is, well, always there, gives me the same
> error.
>
> Is there a way around this? Thanks!

Hi Mike,

If myFunction always returns a structure with the same fields then you
can do the first one to figure that out and continue:

m = myFunction(x(1))
m = repmat(m,1,numM);
for n = 2:numM
m(n) = myFunction(x(n));
end

If the fields returned by myFunction vary from call to call then you
have no choice but to put them in a cell array:

m = cell(1,numM);
for n = 1:numM
m{n} = myFunction(x(n));
end


Doug
(also at UR)

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.
From: Jan Simon on
Dear Mike!

> m=struct([]);
> for n=1:numN
> m(n)=myFunction(x);
> end
> returns:
> > ??? Subscripted assignment between dissimilar structures

What about an automatical pre-allocation by starting the loop from the back:
for n = numN:-1:1
m(n) = myFunction(x);
end

Or if myFunction returns different fields for each call:
for n = 1:numN
S = myFunction(x);
Fields = fieldnames(S);
Data = struct2cell(S);
for iField = 1:length(Fields)
m(n).(Fields{iField}) = Data{iField};
end
end

This creates empty data for the other elements of [m] automatically. The performance of this method is most likely worse than the direct struct copy, but if [numM] is small this might be negligible.

Good luck, Jan
From: Andy on
% A silly solution that require minimal code changes:

m=struct('a',[]); % 'a' is a dummy level of the structure
for n=1:numN
m(n).a=myFunction(x);
end

% Does this return an error?

% Of course, when getting values you will need to type an extra .a
% as in: m(2).a.fieldname1 instead of m(2).fieldname1
From: Mike Pesavento on
"Andy " <theorigamist(a)gmail.com> wrote in message <hinv3t$30s$1(a)fred.mathworks.com>...
> % A silly solution that require minimal code changes:
>
> m=struct('a',[]); % 'a' is a dummy level of the structure
> for n=1:numN
> m(n).a=myFunction(x);
> end
>
> % Does this return an error?

Andy, I believe that method would still return an error (not sure, haven't tried it explicitly). It might not, but definitely makes the code a bit more difficult to read, and I'm not sure about the technical specifics, but at casual glance looks like it obfuscates the point behind initializing a struct in the first place.


"Jan Simon" <matlab.THIS_YEAR(a)nMINUSsimon.de> wrote in message <hinu8j$891$1(a)fred.mathworks.com>...
> Dear Mike!
>
> > m=struct([]);
> > for n=1:numN
> > m(n)=myFunction(x);
> > end
> > returns:
> > > ??? Subscripted assignment between dissimilar structures
>
> What about an automatical pre-allocation by starting the loop from the back:
> for n = numN:-1:1
> m(n) = myFunction(x);
> end
>
> Or if myFunction returns different fields for each call:
> for n = 1:numN
> S = myFunction(x);
> Fields = fieldnames(S);
> Data = struct2cell(S);
> for iField = 1:length(Fields)
> m(n).(Fields{iField}) = Data{iField};
> end
> end
>
> This creates empty data for the other elements of [m] automatically. The performance of this method is most likely worse than the direct struct copy, but if [numM] is small this might be negligible.
>
> Good luck, Jan

Jan,
Going backwards might work, didn't think of that. Your other solution looks like it's just manually dealing out the data back into the struct, but should work. My numM is on the order of 100, just for reference.
The point of the post was to see if there was a relatively quick and efficient way to initialize the struct, where adding a bunch of extra lines of code (and nested for loops), although effective, somewhat defeats my original purpose.

Thank you everyone for the replies!